1.求二元组异或的三次方的和。k为位数,nk<=2000000。

n比较小时,直接两两枚举并用bitset计算。

k比较小时,按照位数进行分组,那么考虑贡献(三个位置)分别在一个组、两个组、三个组里的,枚举这些组并用FWT合并。

  1 #include<bits/stdc++.h>
  2 #define fo(i,a,b)for(int i=a,_e=b;i<=_e;++i)
  3 #define fd(i,a,b)for(int i=b,_e=a;i>=_e;--i)
  4 #define ff(i,a,b)for(int i=a,_e=b;i<_e;++i)
  5 #define ul unsigned long long
  6 #define ui unsigned int
  7 using namespace std;
  8 const int N=2e6+5,mo=998244353;
  9 int tot_time;
 10 int n,k,x,_n,_k;
 11 ul ans;
 12 vector<ul>b[N][2],a[N];
 13 namespace bl_n{
 14     void work_n(){
 15         ui mul=((ul)1<<63)%mo,v;
 16         bool is=(k-1)%63>31;
 17         fo(i,1,n)
 18             fo(j,i+1,n){
 19                 v=is?(a[i][_k]^a[j][_k])%mo:a[i][_k]^a[j][_k];
 20                 fd(l,0,_k-1)
 21                     v=((ul)v*mul+(a[i][l]^a[j][l]))%mo;
 22                 ans=((ul)v*v%mo*v+ans)%mo;
 23             }
 24     }
 25 }
 26 namespace bl_bitset_k{
 27     ul is[4][N/64+5];
 28     ui _[1005];
 29     #define ct __builtin_popcountll
 30     void work_k(){
 31         _[0]=1;
 32         fo(i,1,k-1)_[i]=_[i-1]*2%mo;
 33         fo(i,0,k-1){
 34             int c[2]={0,0};
 35             fo(p,0,1)fo(j,0,_n)c[p]+=ct(b[i][p][j]);
 36             ans=((ul)_[i]*_[i]%mo*_[i]%mo*c[0]%mo*c[1]+ans)%mo;
 37             fo(l,i+1,k-1){
 38                 int c[4]={0,0,0,0};
 39                 fo(p,0,3){
 40                     int o=(p&2)>0,u=p&1;
 41                     fo(j,0,_n)is[p][j]=b[i][o][j]&b[l][u][j],c[p]+=ct(is[p][j]);
 42                 }
 43                 ans=((ul)_[i]*_[l]%mo*(_[i]+_[l])%mo*(((ul)c[0]*c[3]+(ul)c[1]*c[2])%mo)*3+ans)%mo;
 44                 fo(p,l+1,k-1){
 45                     int c[8]={0,0,0,0,0,0,0,0};
 46                     fo(o,0,3)fo(q,0,1)
 47                         fo(j,0,_n)c[o*2+q]+=ct(is[o][j]&b[p][q][j]);
 48                     ans=((ul)_[i]*_[l]%mo*_[p]%mo*(((ul)c[0]*c[7]+(ul)c[1]*c[6]+(ul)c[2]*c[5]+(ul)c[3]*c[4])%mo)*6+ans)%mo;
 49                 }
 50             }    
 51         }
 52     }
 53 }
 54 namespace divide_fwt_k{
 55     const int Q=(1<<15)+5,M=160;
 56     int f[Q],K,L;
 57     int c[M][M][M],c2[M][M],c3[M];
 58     vector<int>bit[1005];
 59     ui _[1005];
 60     bool is_do[M][M],is_do2[M];
 61     inline void up(int &x){x+=(x>>31)&mo;}
 62     int ny(int x){
 63         int t=1;
 64         fo(i,1,x)t=t&1?t+mo>>1:t>>1;
 65         return t;
 66     }
 67     void fwt_xor(int *a){
 68         int A;
 69         for(int i=1;i<(1<<K);i<<=1)for(int j=0;j<(1<<K);j+=i*2)
 70             ff(l,0,i)A=a[j+l],up(a[j+l]+=a[i+j+l]-mo),up(a[i+j+l]=A-a[i+j+l]);
 71     }
 72     void fwt_xor_and(int *a){
 73         int A;
 74         for(int i=1;i<(1<<K);i<<=1)for(int j=0;j<(1<<K);j+=i*2)
 75             ff(l,0,i)A=a[j+l],up(a[j+l]+=a[j+l]-mo),up(a[i+j+l]=A-a[i+j+l]);
 76         int y=ny(K);
 77         ff(i,0,1<<K)a[i]=(ul)a[i]*y%mo;
 78     }
 79     void ck_two_3(int x,int y,int shx,int shy){
 80         if(!is_do[x][y]){
 81             is_do[x][y]=1;
 82             ff(x0,0,L)ff(x1,x0+1,L)ff(y0,0,L)
 83                 c[x*L+x0][x*L+x1][y*L+y0]=f[(1<<x0+shx)|(1<<x1+shx)|(1<<y0+shy)];
 84             ff(x0,0,L)ff(y0,0,L)ff(y1,y0+1,L)
 85                 c[x*L+x0][y*L+y0][y*L+y1]=f[(1<<x0+shx)|(1<<y0+shy)|(1<<y1+shy)];
 86             ff(x0,0,L)ff(y0,0,L)
 87                 c2[x*L+x0][y*L+y0]=f[(1<<x0+shx)|(1<<y0+shy)];
 88         }
 89     }
 90     void ck_one_3(int x,int shx){
 91         if(!is_do2[x]){
 92             is_do2[x]=1;
 93             ff(x0,0,L)ff(x1,x0+1,L)ff(x2,x1+1,L)
 94                 c[x*L+x0][x*L+x1][x*L+x2]=f[(1<<x0+shx)|(1<<x1+shx)|(1<<x2+shx)];
 95             ff(x0,0,L)ff(x1,x0+1,L)
 96                 c2[x*L+x0][x*L+x1]=f[(1<<x0+shx)|(1<<x1+shx)];
 97             ff(x0,0,L)
 98                 c3[x*L+x0]=f[(1<<x0+shx)];
 99         }
100     }
101     void init(){
102         for(;(ul)3*(L+1)*(1<<3*(L+1))<=n;)++L;L=min(L,5);
103     }
104     void work_k(){
105         init();
106         K=L*3;
107         int G=(k-1)/L;
108         fo(j,0,G){
109             int S=j*L,E=(j+1)*L-1,L2=64-(S&63);
110             bit[j].resize(n+1);
111             fo(i,1,n)
112                 bit[j][i]=(S>>6)==(E>>6)?a[i][S>>6]>>(S&63)&((1<<L)-1):(a[i][S>>6]>>(S&63))|(a[i][E>>6]&((1<<L-L2)-1))<<L2;
113         }
114         fo(j,0,G)fo(l,j+1,G)fo(p,l+1,G){
115             memset(f,0,1<<K+2);
116             fo(i,1,n)++f[(bit[j][i]<<L*2)|(bit[l][i]<<L)|bit[p][i]];
117             fwt_xor(f);
118             ff(i,0,1<<K)f[i]=(ul)f[i]*f[i]%mo;
119             fwt_xor_and(f);
120             ff(j0,0,L)ff(l0,0,L)ff(p0,0,L)
121                 c[j*L+j0][l*L+l0][p*L+p0]=f[(1<<j0+L*2)|(1<<l0+L)|(1<<p0)];
122             ck_two_3(j,l,L*2,L);
123             ck_two_3(j,p,L*2,0);
124             ck_two_3(l,p,L,0);
125             ck_one_3(j,L*2);
126             ck_one_3(l,L);
127             ck_one_3(p,0);
128         }
129         _[0]=1;
130         fo(i,1,k-1)_[i]=_[i-1]*2%mo;
131         fo(i,0,k-1){
132             ans=((ul)_[i]*_[i]%mo*_[i]%mo*c3[i]+ans)%mo;
133             fo(l,i+1,k-1){
134                 ans=((ul)_[i]*_[l]%mo*(_[i]+_[l])%mo*c2[i][l]*3+ans)%mo;
135                 fo(p,l+1,k-1)
136                     ans=((ul)_[i]*_[l]%mo*_[p]%mo*c[i][l][p]*6+ans)%mo;
137             }
138         }
139         ans=ans*(mo+1>>1)%mo;
140     }
141 }
142 ui seed;
143 #define get_next()(seed^=seed<<13,seed^=seed>>17,seed^=seed<<5)
144 int main(){
145     freopen("xor.in","r",stdin);
146     freopen("xor.out","w",stdout);
147     cin>>n>>k>>x>>seed;
148     _n=n>>6;
149     if(k<=150){
150         divide_fwt_k::init();
151         if(!divide_fwt_k::L||(k-1)/divide_fwt_k::L<2){
152             _k=k-1>>6;
153             fo(i,0,k-1)fo(o,0,1)b[i][o].resize(_n+1);
154             fo(i,1,n){
155                 a[i].resize(_k+1);
156                 fo(j,0,k-1){
157                     get_next();
158                     if(seed&1)
159                         a[i][j>>6]|=(ul)1<<(j&63),b[j][1][i>>6]|=(ul)1<<(i&63);
160                     else 
161                         b[j][0][i>>6]|=(ul)1<<(i&63);    
162                 }
163             }
164             bl_bitset_k::work_k();
165         }else{
166             _k=k-1>>6;
167             fo(i,1,n){
168                 a[i].resize(_k+1);
169                 fo(j,0,k-1){
170                     get_next();
171                     if(seed&1)
172                         a[i][j>>6]|=(ul)1<<(j&63);
173                 }
174             }
175             divide_fwt_k::work_k();
176         }
177     }else{
178         _k=(k-1)/63;
179         fo(i,1,n){
180             a[i].resize(_k+1);
181             fo(j,0,k-1){
182                 get_next();
183                 if(seed&1)
184                     a[i][j/63]|=(ul)1<<(j%63);
185             }
186         }
187         bl_n::work_n();
188     }
189     cout<<ans<<endl;
190 }
View Code

3.确定一个排列,每次可以询问一个排列,返回正确的位置的个数。要求nlogn次询问。

只考虑n为偶数的情况。对于两个位置i和j,如果交换以后询问从0变为1或2,那么i和j中至少有一个位置上应为p[i]或p[j]。这样,连边所有询问会从0变为1或2的点对(i,j),最后图一定由环构成,定向以后就确定了排列。

考虑选出一些没有公共点的边,将这些边的两端进行交换后,如果询问从0变为了一个正数,那么这些边中至少有一条出现在环中的边。这样就能进行二分找到有用的边。

进行n-1轮,每次需要找到n/2条边,有这样一种构造:从0开始标号,第x轮选择i+j=x(mod n-1)的点对和2p=x(mod n-1)的点对。

如果是奇数,多加一个点。

 1 #include "game.h"
 2 #include<bits/stdc++.h>
 3 #define fo(i,a,b)for(int i=a,_e=b;i<=_e;++i)
 4 #define fd(i,a,b)for(int i=b,_e=a;i>=_e;--i)
 5 #define P pair<int,int>
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define ll long long
10 #define add(x,y)(su[x]<2&&su[y]<2?d.pb(P(x,y)),0:0)
11 using namespace std;
12 const int N=10005;
13 int n,lim,nn,cs,las,now,su[N];
14 vector<int>ans,a,q,e[N];
15 vector<int>c[N];
16 vector<P>d;
17 bool us[N];
18 int ran(int x,int y){return ((ll)RAND_MAX*rand()+rand())%(y-x+1)+x;}
19 void shuffle(vector<int> &a){
20     fo(i,0,n-1)swap(a[i],a[ran(0,i)]);
21 }
22 void link(int x,int y,int ct){
23     e[x].pb(y);e[y].pb(x);
24     su[x]+=ct;su[y]+=ct;
25 }
26 int get(int l,int r){
27     q=a;
28     fo(i,l,r)swap(q[d[i].fi-1],q[d[i].se-1]);
29     return count(q);
30 }
31 void find(int l,int r,int cnt){
32     if(!cnt)return;
33     if(l==r){
34         link(d[l].fi,d[l].se,cnt);
35         return;
36     }
37     int m=l+r>>1,cnt2=get(l,m);
38     find(l,m,cnt2);
39     find(m+1,r,cnt-cnt2);
40 }
41 void dg(int x){
42     us[x]=1;c[cs].pb(x-1);
43     for(int i:e[x])if(!us[i])dg(i);
44 }
45 std :: vector<int> guess(int _n, int _limit) {
46     srand(998244353);
47 //    srand(time(0)+*(new(int)));
48     n=_n;lim=_limit;
49     fo(i,1,n)a.pb(i);
50     for(;;){
51         shuffle(a);
52         if(!count(a))break;
53     }
54     nn=n&1?n:n-1;
55     fo(i,0,nn-1){
56         d.clear();
57         fo(j,0,nn-1){
58             int x=j+1,y=(i-j+nn)%nn+1;
59             if(x==y&&(~n&1))add(x,n);
60             else{
61                 if(x<y)add(x,y);
62             }
63         }
64         if(d.size())
65             find(0,d.size()-1,get(0,d.size()-1));
66     }
67     fo(i,1,n)if(!us[i])++cs,dg(i);
68     ans=a;
69     fo(i,1,cs){
70         int s=c[i].size();
71         fo(j,0,s-1)ans[c[i][j]]=a[c[i][(j+1)%s]];
72         now=count(ans);
73         if(las==now){
74             fo(j,0,s-1)ans[c[i][j]]=a[c[i][(j+s-1)%s]];
75             now+=s;
76         }
77         las=now;
78     }
79     return ans;
80 }
View Code

 

 posted on 2020-09-08 18:14  GreenDuck  阅读(200)  评论(0编辑  收藏  举报