[loj502]ZQC的截图
给每一个人一个随机数$R_{i}$,将一个消息中所有人的的$R_{i}$在三进制下相加(多次出现需要多个$R_{i}$),最终之和若为0,即判定答案为-1,若为某个$R_{i}$或$R_{i}+R_{i}$(三进制下),则为$i$,否则为-2
显然这一做法是随机的,但其每一次失败都意味者结果为0,但存在若干个$R_{i}$出现次数不为3的倍数,且其之和恰为0(关于结果是$R_{i}$或$R_{i}+R_{i}$可以看作减去$R_{i}$或$R_{i}+R_{i}$)
注意到$R_{i}$是随机的,因此若干个$R_{i}$之和也是随机的,为0的概率恰为$\frac{1}{V}$(其中$V$为值域,应为3的幂次)
但事实上,这里还有两个问题:
1.如何快速判定是否为$R_{i}$或$R_{i}+R_{i}$,由于有$o(n)$个值,且空间仅有128MB,哈希范围仅能为$10^{7}$,因此需要在哈希的基础上,每一个位置再开一个vector(此时哈希范围仅能为$10^{6}$)
2.三进制下暴力计算是$\log_{3}V$的,选择$V=3^{35}$,并预处理出$3^{7}$以内任意两数加法,那么单次加法的复杂度降为$o(5)$(这些都只是常数优化,实际理论复杂度还是$o(\log_{3}V)$)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 #define K 2187 5 #define mod 1000003 6 #define ll long long 7 vector<int>mat[mod]; 8 int n,m,x,y,ans,init[K][K]; 9 ll R[N],dep[N<<1]; 10 int read(){ 11 int x=0,flag=0; 12 char c=getchar(); 13 while ((c<'0')||(c>'9')){ 14 if (c=='-')flag=1; 15 c=getchar(); 16 } 17 while ((c>='0')&&(c<='9')){ 18 x=x*10+c-'0'; 19 c=getchar(); 20 } 21 if (flag)x=-x; 22 return x; 23 } 24 void write(int x){ 25 if (x<0){ 26 putchar('-'); 27 x=-x; 28 } 29 int num[11]; 30 num[0]=0; 31 while (x){ 32 num[++num[0]]=x%10; 33 x/=10; 34 } 35 if (!num[0])putchar('0'); 36 for(int i=num[0];i;i--)putchar(num[i]+'0'); 37 putchar('\n'); 38 } 39 int add_low(int x,int y){ 40 int s=1,ans=0; 41 for(int i=0;i<7;i++){ 42 ans=ans+(x+y)%3*s; 43 s*=3,x/=3,y/=3; 44 } 45 return ans; 46 } 47 ll add_high(ll x,ll y){ 48 ll s=1,ans=0; 49 for(int i=0;i<5;i++){ 50 ans=ans+init[x%K][y%K]*s; 51 s*=K,x/=K,y/=K; 52 } 53 return ans; 54 } 55 int main(){ 56 srand(time(0)); 57 for(int i=0;i<K;i++) 58 for(int j=0;j<K;j++)init[i][j]=add_low(i,j); 59 n=read(),m=read(); 60 for(int i=1;i<=n;i++){ 61 for(int j=0;j<35;j++)R[i]=R[i]*3+rand()%3; 62 mat[R[i]%mod].push_back(i); 63 mat[add_high(R[i],R[i])%mod].push_back(i); 64 } 65 for(int i=1;i<=m;i++){ 66 x=read(),y=read(); 67 x^=ans,y^=ans; 68 dep[i]=add_high(dep[y],R[x]); 69 if (!dep[i])ans=-1; 70 else{ 71 ans=-2; 72 for(int j=0;j<mat[dep[i]%mod].size();j++){ 73 ll x=R[mat[dep[i]%mod][j]]; 74 if ((x==dep[i])||(add_high(x,x)==dep[i])){ 75 ans=mat[dep[i]%mod][j]; 76 break; 77 } 78 } 79 } 80 write(ans); 81 } 82 return 0; 83 }