• CF1408I. Bitwise Magic


    题目描述

    题解

    首先有一个显然的重要结论:一个数减k后只会影响到最后log k位

    所以先把异或和求出来,问题变成给出一些集合((0,x ;xor ;(x-1),x ;xor ;(x-2),...x ;xor ;(x-k))),在里面选择一些数异或起来求方案

    这样的组数很少,因为只和最后log k位以及第(log k)位后第一个1的位置有关(最后log k位加上以log k开始的一段1),所以是c^2的,丢到数组h[i,j]里表示第i位是第一个1后log k位为j

    (以下均把k换成c)

    可以预处理一个数组g[i,j,k,0/1]表示后面的第一个1在第i位,选了j个,最后log c位异或为k,第i位是否被异或

    这个可以压成一个二项式(x^iy^j)表示个数和异或值,0/1也压进去

    算方案转EGF,FWT后快速幂,这部分时间是O(c^6)(枚举h[i,j]2个c快速幂1个c乘法3个c)

    根据0/1的奇偶可以搞出g[i,0/1]表示第一个1在i,选完后log k~i是否反转

    之后dp合并,设f[s]表示当前合并的位,每次考虑下一位转移即可,s的范围是2^c/c,里面的乘法是c^3,所以时间是O(2^c*c^2),已经可以过了

    后一部分的常数非常大,所以可以ln后变成加法,可以少掉一个c

    如果时间写错了变成2^c*c^3可能会过不了,尽管在本机只跑了1.9s

    code

    没写lnexp

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define add(a,b) a=((a)+(b))%998244353
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    #define mod 998244353
    #define Mod 998244351
    #define two 499122177
    #define ll long long
    //#define file
    using namespace std;
    
    ll h[17][17],ans[65536],N,jc[17],Jc[17];
    int a[65536],p[17],n,K,L,c,i,j,k,l,Sum,x;
    
    struct type{ll a[32];void clear() {memset(a,0,sizeof(a));}};
    struct Type{type a[17]; void clear() {int i; fo(i,0,16) a[i].clear();}} g[17][2],G[17],f[4096],F[4096],s,I;
    void turn(type &a,int tp)
    {
    	int i,j,k,l,S=p[L+1],s1=2,s2=1;
    	ll u,v;
    	
    	fo(i,1,L+1)
    	{
    		S>>=1;
    		fo(j,0,S-1)
    		{
    			fo(k,0,s2-1)
    			{
    				u=a.a[j*s1+k],v=a.a[j*s1+k+s2];
    				a.a[j*s1+k]=(u+v)%mod;
    				a.a[j*s1+k+s2]=(u-v)%mod;
    				if (tp==-1) a.a[j*s1+k]=a.a[j*s1+k]*two%mod,a.a[j*s1+k+s2]=a.a[j*s1+k+s2]*two%mod;
    			}
    		}
    		s1<<=1,s2<<=1;
    	}
    }
    type operator +(type a,type b)
    {
    	static type c;
    	int i;
    	fo(i,0,p[L+1]-1) c.a[i]=(a.a[i]+b.a[i])%mod;
    	return c;
    }
    type operator *(type a,type b)
    {
    	static type c;
    	int i;
    	fo(i,0,p[L+1]-1) c.a[i]=(a.a[i]*b.a[i])%mod;
    	return c;
    }
    
    Type operator *(Type a,Type b)
    {
    	static Type c;
    	int i,j,k,l;
    	c.clear();
    	
    	fo(i,0,K)
    	{
    		fo(j,0,i)
    		c.a[i]=c.a[i]+(a.a[j]*b.a[i-j]);
    	}
    	return c;
    }
    void Turn(Type &a,int tp)
    {
    	int i;
    	fo(i,0,K)
    	turn(a.a[i],tp);
    }
    void TurnEGF(Type &a)
    {
    	int i,j;
    	fo(i,0,K)
    	{
    		fo(j,0,p[L+1]-1)
    		a.a[i].a[j]=a.a[i].a[j]*Jc[i]%mod;
    	}
    }
    
    ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
    Type Qpower(Type a,int b) {static Type ans;ans=I;while (b) {if (b&1) ans=ans*a;a=a*a;b>>=1;} return ans;}
    void init()
    {
    	int i;
    	p[0]=jc[0]=1;
    	fo(i,1,16) p[i]=p[i-1]*2,jc[i]=jc[i-1]*i%mod;
    	Jc[16]=qpower(jc[16],Mod);
    	fd(i,15,0) Jc[i]=Jc[i+1]*(i+1)%mod;
    }
    
    void dp()
    {
    	int I,i,j,k,l,x,S=1;
    	
    	f[0]=g[c][0];
    	fd(I,c-1,L)
    	{
    		fo(i,0,S-1)
    		{
    			l=i&1;
    			F[i*2+l]=f[i]*g[I][0];
    			F[i*2+(!l)]=f[i]*g[I][1];
    		}
    		fo(i,0,S*2-1) f[i]=F[i],F[i].clear();
    		S<<=1;
    	}
    	
    	fo(x,0,p[c-L]-1)
    	{
    		Turn(f[x],-1);
    		fo(k,0,p[L]-1)
    		add(ans[k+x*p[L]],f[x].a[K].a[k]);
    	}
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF1408I.in","r",stdin);
    //	freopen("CF1408I.out","w",stdout);
    	#endif
    	
    	init();
    	scanf("%d%d%d",&n,&K,&c);
    	
    	L=ceil(log2(K));
    	fo(i,1,n)
    	{
    		scanf("%d",&x),Sum^=x;
    		
    		fo(l,L,c-1)
    		if (x&p[l])
    		break;
    		
    		k=x&(p[L]-1);
    		++h[l][k];
    	}
    	
    	I.a[0].a[0]=1,Turn(I,1);
    	fo(i,L,c) G[i]=I;
    	fo(i,L,c)
    	{
    		fo(j,0,p[L]-1)
    		if (h[i][j])
    		{
    			s.clear();
    			fo(k,0,min(j,K))
    			++s.a[k].a[j^(j-k)];
    			if (j<K)
    			{
    				fo(k,j+1,K)
    				++s.a[k].a[j^(p[L]+j-k)^p[L]];
    			}
    			TurnEGF(s),Turn(s,1);
    			G[i]=G[i]*Qpower(s,h[i][j]);
    		}
    	}
    	fo(i,L,c)
    	{
    		Turn(G[i],-1);
    		fo(k,0,K)
    		{
    			fo(l,0,p[L]-1)
    			{
    				add(g[i][0].a[k].a[l],G[i].a[k].a[l]);
    				add(g[i][1].a[k].a[l],G[i].a[k].a[l^p[L]]);
    			}
    		}
    		Turn(g[i][0],1),Turn(g[i][1],1);
    	}
    	dp();
    	fo(i,0,p[c]-1) ans[i]=(ans[i]+mod)%mod*jc[K]%mod;
    	
    	N=qpower(qpower(n,K),Mod);
    	fo(i,0,p[c]-1)
    	printf("%lld ",ans[i^Sum]*N%mod);
    	printf("
    ");
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    C++ template —— 模板中的名称(三)
    关于烂代码的那些事(下)
    关于烂代码的那些事(中)
    关于烂代码的那些事(上)
    比尔的村庄:创业是选择做赚钱的事,还是值钱的事?
    C++ template —— 深入模板基础(二)
    依赖倒置,控制反转,依赖注入
    JAVA中限制接口流量、并发的方法
    SVN同步时忽略特定文件或文件夹
    MySQL中查询表及索引大小的方法
  • 原文地址:https://www.cnblogs.com/gmh77/p/13799310.html
Copyright © 2020-2023  润新知