@ysner
2018-07-27T11:02:11.000000Z
字数 2964
阅读 3495
数论
给出一个大小为的非负整数集合,等概率地选取个子集中的一个,设为子集中所有数的异或和,求所有情况之和。
暴搜。
先从开始吧。
题目转化为求所有情况之和。
而每位为(对答案有贡献)决定于子集中该位为的数的个数为奇数。
于是我们可以数位分开单独讨论。
假设子集中该位为的数的个数为。
则选出奇数个的方案数为。
由于该位为的数对答案没有影响,可以任选,故方案数还需乘上,即为该位对答案的贡献。
所有位贡献相加即可。
(然而只有是对的,下面内容都有问题)
处理需要化式子:
有没有发现枚举特别傻逼?这种情况和一模一样。
我们强制不降,然后乘上系数即可。(系数计算机爆算即可)
这样复杂度会除,刚好能过。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define re register#define il inline#define ll unsigned long long#define max(a,b) ((a)>(b)?(a):(b))#define min(a,b) ((a)<(b)?(a):(b))#define fp(i,a,b) for(re int i=a;i<=b;i++)#define fq(i,a,b) for(re int i=a;i>=b;i--)using namespace std;const int N=300,mod=998244853;ll n,k,num[N],s[70][70][70][70],C[200][200],jc[200],ans;il ll gi(){re ll x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t;}il ll ksm(re ll x,re ll n){re ll S=1,T=x;while(n){if(n&1) S=S*T%mod;T=T*T%mod;n>>=1;}return S;}il void solve(re ll s){re ll tot=0;fp(i,0,64){if((1ll<<i)>s) break;if((1ll<<i)&s) ++tot;}(ans+=ksm(tot,k))%=mod;}il void dfs(re ll x,re ll s){if(x>n) {solve(s);return;}fp(i,0,1)if(i) dfs(x+1,s^num[x]);else dfs(x+1,s);}il void check(re int *a){sort(a+1,a+5);s[a[1]][a[2]][a[3]][a[4]]++;}il void Pre(){re int p[5];C[0][0]=1;fp(i,1,n){C[i][0]=1;fp(j,1,i) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;}jc[0]=1;fp(i,1,n) jc[i]=(jc[i-1]<<1)%mod;fp(a,0,63) fp(b,0,63) fp(c,0,63) fp(d,0,63) p[1]=a,p[2]=b,p[3]=c,p[4]=d,check(p);}int main(){freopen("xor.in","r",stdin);freopen("xor.out","w",stdout);n=gi();k=gi();fp(i,1,n) num[i]=gi();if(n<=20) dfs(1,0);else if(k==1){Pre();fp(a,0,63){re ll tot=0,sum=0;fp(i,1,n)if(num[i]&(1ll<<a)) ++tot;for(re int i=1;i<=tot;i+=2) (sum+=C[tot][i])%=mod;sum=sum*jc[n-tot]%mod;(ans+=sum)%=mod;}}else if(k==2){Pre();fp(a,0,63)fp(b,0,63){re ll tot=0,sum=0;fp(i,1,n)if((num[i]&(1ll<<a))&&(num[i]&(1ll<<b))) ++tot;for(re int i=1;i<=tot;i+=2) (sum+=C[tot][i])%=mod;sum=sum*jc[n-tot]%mod;(ans+=sum)%=mod;}}else if(k==3){Pre();fp(a,0,63)fp(b,0,63)fp(c,0,63){re ll tot=0,sum=0;fp(i,1,n)if((num[i]&(1ll<<a))&&(num[i]&(1ll<<b))&&(num[i]&(1ll<<c))) ++tot;for(re int i=1;i<=tot;i+=2) (sum+=C[tot][i])%=mod;sum=sum*jc[n-tot]%mod;(ans+=sum)%=mod;}}else if(k==4){Pre();fp(a,0,63)fp(b,a,63)fp(c,b,63)fp(d,c,63){re ll tot=0,sum=0;fp(i,1,n)if((num[i]&(1ll<<a))&&(num[i]&(1ll<<b))&&(num[i]&(1ll<<c))&&(num[i]&(1ll<<d))) ++tot;for(re int i=1;i<=tot;i+=2) (sum+=C[tot][i])%=mod;sum=sum*jc[n-tot]%mod;(ans+=sum)%=mod;}}printf("%lld\n",ans);fclose(stdin);fclose(stdout);return 0;}
