• 异或


    https://zybuluo.com/ysner/note/1228125

    题面

    给出一个大小为(n)的非负整数集合({a_1,a_2,...,a_n}),等概率地选取(2^n)个子集中的一个,设(S)为子集中所有数的异或和(overline{s_1s_2s_3...s_h}_{(2)}),求所有情况((s_1+s_2+s_3+...+s_h)^k)之和。

    • (20pts nleq20)
    • (60pts k=1,2,3,4)
    • (100pts nleq100,hleq63)

    解析

    (20pts)算法

    (O(2^n))暴搜。

    (60pts)算法

    先从(k=1)开始吧。
    题目转化为求所有情况(s_1+s_2+s_3+...)之和。
    而每位(s)(1)(对答案有贡献)决定于子集中该位为(1)的数的个数为奇数。
    于是我们可以数位分开单独讨论。

    假设子集中该位为(1)的数的个数为(tot)
    则选出奇数个的方案数为(C_{tot}^1+C_{tot}^3+C_{tot}^5...)
    由于该位为(0)的数对答案没有影响,可以任选,故方案数还需乘上(2^{n-tot}),即为该位对答案的贡献。
    所有位贡献相加即可。

    处理(k=4)需要化式子:

    [sum(s_1+s_2+s_3+...+s_h)^4 ]

    [=sum(s_1+s_2+...)*(s_1+s_2+...)*(s_1+s_2+...)*(s_1+s_2+...) ]

    [=sumsum_{a=1}^hsum_{b=1}^hsum_{c=1}^hsum_{d=1}^hs_as_bs_cs_d ]

    于是枚举(a,b,c,d),统计(s_a,s_b,s_c,s_d)四位都不为(0)的数的个数,组合数处理(当然要取奇数个)即可。
    复杂度(O(h^kn))(k=4)时会达到(O(10^9))

    有没有发现枚举(a=2,b=1,c=1,d=1)特别傻逼?这种情况和(a=1,b=1,c=1,d=2)一模一样。
    我们强制(a,b,c,d)不降,然后乘上系数即可。(系数计算机爆算即可)
    这样复杂度会除(4*3*2*1=24),刚好能过。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #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 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,n) 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()
    {
    	n=gi();k=gi();
    	fp(i,1,n) num[i]=gi();
    	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*s[a][b][c][d]%mod;
    		(ans+=sum)%=mod;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    程序模块化 与 单元测试
    【集美大学1411_助教博客】2017软件工程开跑啦。。。。
    沟通很重要
    参赛感言
    助教日志_期末总结
    助教日志_【沈阳航空航天大学软件工程 1,2班】期末排行
    [数据库事务与锁]详解一: 彻底理解数据库事务
    [数据库事务与锁]详解二: 数据库的读现象浅析
    [数据库事务与锁]详解三: 深入分析事务的隔离级别
    [数据库事务与锁]详解四: 数据库的锁机制
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9378508.html
Copyright © 2020-2023  润新知