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 }
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 }