UOJ #121 [NOI2013 D1T1] 向量內積

兩個 dd 維向量 A=[a1,a2,,ad]A=[a1,a2,…,ad] 與 B=[b1,b2,,bd]B=[b1,b2,…,bd] 的內積爲其相對應維度的權值的乘積和,即:

A,B=i=1daibi=a1b1+a2b2++adbd⟨A,B⟩=∑i=1daibi=a1b1+a2b2+⋯+adbd

現在有 nn 個 dd 維向量 x1,x2,,xnx1,x2,…,xn,小喵喵想知道是否存在兩個向量的內積爲 kk 的倍數。請幫助她解決這個問題。

輸入格式

第一行包含 33 個正整數 n,d,kn,d,k,分別表示向量的個數,維數以及待檢測的倍數。

接下來 nn 行每行有 dd 個非負整數,其中第 ii 行的第 jj 個整數表示向量 xixi 的第 jj 維權值 xi,jxi,j

輸出格式

包含兩個整數,用空格隔開。

如果存在兩個向量 xp,xqxp,xq 的內積爲 kk 的整數倍,則輸出兩個向量的編號 pp 與 qq (要求 p<qp<q)。如果存在多組這樣的向量組合,輸出其中任意一組即可。

若不存在這樣的向量組合,則輸出兩個 1−1

樣例一

input

3 5 2
1 0 1 0 1
1 1 0 1 0
0 1 0 1 1

output

2 3

explanation

x1,x2=1⟨x1,x2⟩=1x1,x3=1⟨x1,x3⟩=1x2,x3=2⟨x2,x3⟩=2

限制與約定

測試點編號 nn dd kk xi,jxi,j
1 22 2020 22 10≤10
2 55 2020 22 10≤10
3 1010 2020 33 10≤10
4 2020 2020 22 100≤100
5 5050 2020 33 100≤100
6 5050 5050 22 1000≤1000
7 5050 5050 33 3000000≤3000000
8 8080 8080 22 3000000≤3000000
9 100100 100100 33 3000000≤3000000
10 500500 100100 33 3000000≤3000000
11 10001000 100100 22 3000000≤3000000
12 10001000 100100 33 3000000≤3000000
13 1000010000 100100 22 <10<10
14 1000010000 100100 33 <10<10
15 1500015000 100100 22 <10<10
16 1800018000 100100 22 <10<10
17 2000020000 100100 22 <10<10
18 5000050000 3030 33 <10<10
19 8000080000 3030 33 <10<10
20 100000100000 3030 33 <10<10

時間限制:5s5s

空間限制:256MB256MB

下載

樣例數據下載

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

隨機化~

隨機大法真是太神辣!!!

發現k==2或3,所以分開來做。

k==2時,我們發現內積只有0或1,所以我們用^運算i與之前的所有的內積是否與(i-1)%mod相等,不相等的話說明前面一定有與i得出的結果是1的,暴力尋找輸出即可。

但是顯然這樣判斷的誤差非常大,因爲這是取模下的運算。所以我們每次隨機順序,然後判斷它與之前的序列可不可行,只要判斷7-mod次即可。

3的情況同上。

改了半天模數最後發現是id寫成了a……


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int t,n,m,mod,a[100001][101],id[100001],las=1,b[100001],c[101][101];

int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

int rand()
{
	return las=(((long long)las*20000909+2010527)%1000000009)/97; 
}

int sol(int u)
{
	int ans=0;
	if(mod==2) for(int i=1;i<=m;b[i]^=a[u][i],i++) ans^=b[i]&a[u][i];
	else for(int i=1;i<=m;i++)
		  for(int j=1;j<=m;c[i][j]+=a[u][i]*a[u][j],j++)
		    ans+=c[i][j]*a[u][i]*a[u][j];
	return ans%mod;
}

bool jud(int u,int v)
{
	int now=0;
	for(int i=1;i<=m;i++) now+=a[u][i]*a[v][i];
	return !(now%mod);
}

int main()
{
	n=read();m=read();mod=read();
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=m;j++) a[i][j]=read()%mod;
	for(int i=1;i<=n;i++) id[i]=i;t=7-mod;
	while(t--)
	{
		for(int i=2;i<=n;i++) swap(id[i],id[rand()%(i-1)+1]);
		if(mod==2) memset(b,0,sizeof(b));
		else memset(c,0,sizeof(c));
		for(int i=1;i<=n;i++)
		  if(sol(id[i])!=(i-1)%mod)
		    for(int j=1;j<i;j++) if(jud(id[i],id[j]))
		    {
		    	if(id[i]>id[j]) swap(id[i],id[j]);
		    	printf("%d %d\n",id[i],id[j]);
		    	return 0;
		    }
	}
	puts("-1 -1");
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章