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("\n");
fclose(stdin);
fclose(stdout);
return 0;
}