- 给定(n)个(d)维向量,要求找出一对向量满足它们的内积是(k)的倍数。
- (nle10^5,dle30)或(nle2 imes10^4,dle100),(k=2)或(3)
前缀共同判定
以(k=2)为例,如果前(i-1)个向量与(i)的内积模(2)都不为(0)(只能为(1)),那么内积之和模(2)应该与(i-1)同余。
内积的运算是满足分配律的,所以如果前(i-1)个向量的和向量与(i)的内积与(i-1)模(2)不同余,则前(i-1)个向量中必然存在至少一个与(i)的内积模(2)为(0),在确定一个向量的情况下直接去暴力找一趟即可。
当然上述做法存在缺陷,尽管模(2)同余也不一定不存在,因此我们要对给定的向量(random\_shuffle),以防良心出题人的“良心数据”。
而(k=3)有些不太一样,因为模(3)余数不定,也就很难类似判定。
但发现(1^2equiv2^2equiv1(mod 3)),所以我们只要求出前(i-1)个向量与(i)的内积的平方和与(i-1)模(3)是否同余即可。
平方直接大力拆开:((sum_{x=1}^da_{i,x}a_{j,x})^2=sum_{x=1}^dsum_{y=1}^da_{i,x}a_{i,y}a_{j,x}a_{j,y})。因此对每种(a_{j,x}a_{j,y})做个前缀和即可。
代码:(O(nd^2))
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define M 100
using namespace std;
int n,d,k,id[N+5],a[N+5][M+5],s[M+5],ss[M+5][M+5];
namespace FastIO
{
#define FS 100000
#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
char oc,FI[FS],*FA=FI,*FB=FI;
Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}using namespace FastIO;
int main()
{
RI i,j,p,q,t;for(read(n,d,k),i=1;i<=n;++i) for(id[i]=i,j=1;j<=d;++j) read(a[i][j]),a[i][j]%=k;
srand(71717171);W(random_shuffle(id+1,id+n+1),true)//random_shuffle
{
if(k==2) for(i=1;i<=n;++i)//如果k=2
{
for(t=0,p=1;p<=d;++p) t^=a[id[i]][p]&s[p],s[p]^=a[id[i]][p];//统计前i-1个向量与第i个向量内积和
if(t==((i-1)&1)) continue;//如果同余不一定存在
for(j=1;j^i;++j) {for(t=0,p=1;p<=d;++p) t^=a[id[i]][p]&a[id[j]][p];if(!t) break;}//暴力找
return printf("%d %d
",min(id[i],id[j]),max(id[i],id[j])),0;//注意尽管有SPJ,但题面要求必须满足p<q
}
else for(i=1;i<=n;++i)//如果k=3
{
for(t=0,p=1;p<=d;++p) for(q=1;q<=d;++q)
t+=a[id[i]][p]*a[id[i]][q]*ss[p][q],(ss[p][q]+=a[id[i]][p]*a[id[i]][q])%=3;//统计前i-1个向量与第i个向量内积平方和
if(t%3==(i-1)%3) continue;//如果同余不一定存在
for(j=1;j^i;++j) {for(t=0,p=1;p<=d;++p) t+=a[id[i]][p]*a[id[j]][p];if(!(t%3)) break;}//暴力找
return printf("%d %d
",min(id[i],id[j]),max(id[i],id[j])),0;
}
}return 0;
}