https://atcoder.jp/contests/arc116/tasks/arc116_d
dp[k][i]表示当前已经枚举到2^k了,然后背包容量是i的时候方案数是多少
每次枚举当前2^k放多少个去填,因为要是异或=0,所以必须偶数个,然后方案数就是n个里面选t个位置放下这些2^k,就是C(n,t)
k=logm i=m t=m/2^k ,所以复杂度是O((n+m)log^2m) ,感觉n,m=2e4也能过啊
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=1e5+10;
const int mod=998244353;
int n,m;
ll fac[maxl],inv[maxl];
ll dp[21][maxl];
inline ll qp(ll a,ll b)
{
ll ans=1,cnt=a;
while(b)
{
if(b&1) ans=ans*cnt%mod;
cnt=cnt*cnt%mod;
b>>=1;
}
return ans;
}
inline ll c(int n,int r)
{
if(r>n || r<0) return 0;
return fac[n]*inv[n-r]%mod*inv[r]%mod;
}
inline void add(ll &a,ll b)
{
a=(a+b)%mod;
}
int main()
{
scanf("%d%d",&n,&m);
fac[0]=1;
for(int i=1;i<maxl;i++)
fac[i]=fac[i-1]*i%mod;
inv[maxl-1]=qp(fac[maxl-1],mod-2);
for(int i=maxl-2;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
for(int i=0;i<=min(n,m);i+=2)
dp[0][i]=c(n,i);
for(int k=1;k<=20;k++)
for(int i=0;i<=m;i++)
for(int t=0;t<=n;t+=2)
{
if(t*(1<<k)+i>m)
break;
add(dp[k][t*(1<<k)+i],dp[k-1][i]*c(n,t));
}
printf("%lld",dp[20][m]);
return 0;
}