[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 }
View Code

 

posted @ 2021-04-28 15:25  PYWBKTDA  阅读(84)  评论(0编辑  收藏  举报