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。
Output
包含两个整数,用空格隔开。
如果存在两个向量xp,xq的内积为k的整数倍,则输出两个向量的编号p与q(要求p< q)。如果存在多组这样的向量组合,输出其中任意一组即可。
若不存在这样的向量组合,则输出两个-1。
Sample Input
Sample Output
HINT
Source
不会做QAQ
Mektpoy题解
感觉好厉害啊…竟然是转成矩阵来做T_T
取模会导致跑得慢.我的代码里注释掉的那种只跑了2400ms,没注释掉的跑了6600msQAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define GET (ch>='0'&&ch<='9')
#define MAXN 100100
using namespace std;
int n,d,k;
bool flag;
int a[MAXN][110],sum[MAXN],b[MAXN],c[MAXN],top,num[110][110];
int f,ans;
void in(int &x)
{
x=0;char ch=getchar();int flag=1;
while (!GET) flag=ch=='-'?-1:1,ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();x*=flag;
}
bool check(int i,int j)
{
int ret=0;
for (int l=1;l<=d;l++) ret+=a[i][l]*a[j][l],ret%=k;
return !ret;
}
int main()
{
in(n);in(d);in(k);
for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++) in(a[i][j]),a[i][j]%=k,sum[i]+=a[i][j]*a[i][j],sum[i]%=k;
/*for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++) in(a[i][j]),a[i][j]%=k,sum[i]+=a[i][j]*a[i][j];
for (int i=1;i<=n;i++) sum[i]%=k;*/
if (k==2)
{
for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++) b[j]+=a[i][j],b[j]%=k;
for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++) c[i]+=a[i][j]*b[j],c[i]%=k;
for (int i=1;i<=n;i++) c[i]=(c[i]-sum[i]+k)%k;f=(n-1)%k;
/*for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++) b[j]+=a[i][j];
for (int i=1;i<=d;i++) b[i]%=k;
for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++) c[i]+=a[i][j]*b[j];
for (int i=1;i<=n;i++) c[i]=(c[i]%k-sum[i]+(k<<1))%k;f=(n-1)%k;*/
}
else
{
for (int i=1;i<=d;i++)
for (int j=1;j<=d;j++) num[i][j]=++top;
/*for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++)
for (int l=1;l<=d;l++) b[num[j][l]]+=a[i][j]*a[i][l];
for (int i=1;i<=top;i++) b[i]%=k;
for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++)
for (int l=1;l<=d;l++) c[i]+=a[i][j]*a[i][l]*b[num[j][l]];
for (int i=1;i<=n;i++) c[i]=(c[i]%k-sum[i]*sum[i]+(k<<1))%k;f=(n-1)%k;*/
for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++)
for (int l=1;l<=d;l++) b[num[j][l]]+=a[i][j]*a[i][l],b[num[j][l]]%=k;
for (int i=1;i<=n;i++)
for (int j=1;j<=d;j++)
for (int l=1;l<=d;l++) c[i]+=a[i][j]*a[i][l]*b[num[j][l]],c[i]%=k;
for (int i=1;i<=n;i++) c[i]=(c[i]-sum[i]*sum[i]+k)%k;f=(n-1)%k;
}
for (int i=1;i<=n;i++)
{
if (flag) break;
if (f!=c[i]) flag=1,ans=i;
}
if (!flag) {puts("-1 -1");return 0;}
for (int i=1;i<=n;i++)
if (ans!=i&&check(ans,i)) {printf("%d %d\n",min(ans,i),max(ans,i));return 0;}
}