题目描述
两个
现在有
输入格式
第一行包含
接下来
输出格式
包含两个整数,用空格隔开。
如果存在两个向量
若不存在这样的向量组合,则输出两个
样例一
input
3 5 2 1 0 1 0 1 1 1 0 1 0 0 1 0 1 1
output
2 3
explanation
限制与约定
| 测试点编号 |
|
|
|
|
|---|---|---|---|---|
| 1 |
|
|
|
|
| 2 |
|
|
|
|
| 3 |
|
|
|
|
| 4 |
|
|
|
|
| 5 |
|
|
|
|
| 6 |
|
|
|
|
| 7 |
|
|
|
|
| 8 |
|
|
|
|
| 9 |
|
|
|
|
| 10 |
|
|
|
|
| 11 |
|
|
|
|
| 12 |
|
|
|
|
| 13 |
|
|
|
|
| 14 |
|
|
|
|
| 15 |
|
|
|
|
| 16 |
|
|
|
|
| 17 |
|
|
|
|
| 18 |
|
|
|
|
| 19 |
|
|
|
|
| 20 |
|
|
|
|
时间限制:
空间限制:
分析
注意:以下运算都在模k意义下
k=2
我们把这些向量看成一个
令
但是求出
我们令
如果
我们再随机找出一个列向量
然后比较
尽管有出错的概率,但是这个算法还是比较可靠的。
k=3
我们发现
所以,我们令
然后参考
代码
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100000
#define MAXM 100
int n,d,k,a[MAXN+10][MAXM+10],s[MAXN+10],c[MAXM*MAXM+10],g[MAXN+10];
void Read(int &x){
char c;
while(c=getchar(),c!=EOF)
if(c>=\'0\'&&c<=\'9\'){
x=c-\'0\';
while(c=getchar(),c>=\'0\'&&c<=\'9\')
x=x*10+c-\'0\';
ungetc(c,stdin);
return;
}
}
int Get_id(int i,int j){
return (i-1)*d+j;
}
void read(){
Read(n),Read(d),Read(k);
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=d;j++){
Read(a[i][j]);
a[i][j]%=k;
s[i]+=a[i][j]*a[i][j];
}
for(i=1;i<=n;i++)
s[i]%=k;
}
void solve2(){
int i,j,k,sum;
for(i=1;i<=d;i++)
for(j=1;j<=n;j++)
c[i]^=a[j][i];
for(i=1;i<=n;i++)
for(j=1;j<=d;j++)
g[i]^=a[i][j]&c[j];
for(i=1;i<=n;i++)
if(g[i]!=(s[i]^((n-1)&1)))
break;
if(i>n){
puts("-1 -1");
return;
}
for(j=1;j<=n;j++)
if(i!=j){
sum=0;
for(k=1;k<=d;k++)
sum^=a[i][k]&a[j][k];
if(!sum)
break;
}
if(i>j)
swap(i,j);
printf("%d %d\n",i,j);
}
void solve3(){
int i,j,k,sum;
for(i=1;i<=d;i++)
for(j=1;j<=d;j++)
for(k=1;k<=n;k++)
c[Get_id(i,j)]+=a[k][i]*a[k][j];
for(i=d*d;i;i--)
c[i]%=3;
for(i=1;i<=n;i++)
for(j=1;j<=d;j++)
for(k=1;k<=d;k++)
g[i]+=a[i][j]*a[i][k]*c[Get_id(j,k)];
for(i=1;i<=n;i++)
if(g[i]%3!=((n-1)+s[i]*s[i])%3)
break;
if(i>n){
puts("-1 -1");
return;
}
for(j=1;j<=n;j++)
if(j!=i){
sum=0;
for(k=1;k<=d;k++)
sum=(sum+a[i][k]*a[j][k])%3;
if(!sum)
break;
}
if(i>j)
swap(i,j);
printf("%d %d\n",i,j);
}
int main()
{
read();
if(k==2)
solve2();
else
solve3();
}