3243: [Noi2013]向量内积
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1269 Solved: 252
[ Submit][ Status][ Discuss]
Description
两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即:
现有 n 个d 维向量x1,...,xn ,小喵喵想知道是否存在两个向量的内积为k的倍数。请帮助她解决这个问题
Input
第一行包含3个正整数n,d,k,分别表示向量的个数,维数以及待检测的倍数。接下来n行每行有d个非负整数,其中
第i行的第j个整数表示向量xi的第j维权值xi,j。
N<=100000,D<=30,K<=3,Xi,j<10
Output
包含两个整数,用空格隔开。如果存在两个向量xp,xq的内积为k的整数倍,则输出两个向量的编号p与q(要求p<q
)。如果存在多组这样的向量组合,输出其中任意一组即可。若不存在这样的向量组合,则输出两个-1。
Sample Input
2 20 2
0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1
1 0 1 0 1 0 1 1 1 1 0 1 1 1 0 1 1 0 1 0
0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1
1 0 1 0 1 0 1 1 1 1 0 1 1 1 0 1 1 0 1 0
Sample Output
1 2
HINT
新增数据一组,但未重测By TA1111,2016.5.17
Source
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int N = 1E5 + 10;
int n,d,k,pos,g[N],Z[N],W[N],a[N][111],T[N],A[N],B[N];
int Mul_Vector (int x,int y)
{
int ret = 0,*nx = a[x],*ny = a[y];
for (int i = 1; i <= d; i++)
ret += nx[i]*ny[i];
return ret%k;
}
void Print()
{
for (int i = 1; i <= n; i++)
if (i != pos && Mul_Vector(pos,i) == 0)
{printf("%d %d\n",min(i,pos),max(i,pos)); return;}
}
void Solve2()
{
for (int I = 1; I <= 10; I++)
{
int tot = 0;
for (int i = 1; i <= n; i++)
T[i] = rand()%k,tot += T[i];
tot %= k;
for (int i = 1; i <= d; i++) W[i] = 0;
for (int i = 1; i <= n; i++) Z[i] = 0;
for (int j = 1; j <= n; j++)
{
int *na = a[j];
for (int i = 1; i <= d; i++) W[i] += T[j]*na[i];
}
for (int i = 1; i <= d; i++) W[i] %= k;
for (int i = 1; i <= n; i++)
{
int *na = a[i];
for (int j = 1; j <= d; j++) Z[i] += W[j]*na[j];
Z[i] += (1-g[i])*T[i]; Z[i] %= k; Z[i] += k;
if (Z[i] % k != tot) {pos = i; Print(); return;}
}
}
puts("-1 -1");
}
void Solve3()
{
for (int i = 1; i <= n; i++) g[i] = g[i]*g[i]%k;
int D = d*d;
for (int i = 1; i <= D; i++)
{
int t = (i % d == 0)?i/d:i/d+1;
A[i] = t; B[i] = i-(t-1)*d;
}
for (int I = 1; I <= 10; I++)
{
int tot = 0;
for (int i = 1; i <= n; i++)
T[i] = rand()%k,tot += T[i];
tot %= k;
for (int i = 1; i <= D; i++) W[i] = 0;
for (int i = 1; i <= n; i++) Z[i] = 0;
for (int j = 1; j <= n; j++)
{
int *na = a[j];
for (int i = 1; i <= D; i++) W[i] += T[j]*na[A[i]]*na[B[i]];
}
for (int i = 1; i <= D; i++) W[i] %= k;
for (int i = 1; i <= n; i++)
{
int *na = a[i];
for (int j = 1; j <= D; j++) Z[i] += W[j]*na[A[j]]*na[B[j]];
Z[i] += (1-g[i])*T[i]; Z[i] %= k; Z[i] += k;
if (Z[i] % k != tot) {pos = i; Print(); return;}
}
}
puts("-1 -1");
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); d = getint(); k = getint();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= d; j++)
a[i][j] = getint() % k;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= d; j++)
g[i] += a[i][j]*a[i][j];
for (int i = 1; i <= n; i++) g[i] %= k;
if (k == 2) Solve2();
else Solve3();
return 0;
}