今天第一次写blog那就从现在做的第一题开始写吧。。
问题可以转化成取走若干堆使得剩下堆异或和为0。朴素的做法是用
f[i][j][k]
大概表示前
i
堆,已经取的堆数
首先优化时间,由于
∑ai≤107
,可以考虑将
ai
从小到大排序,对于每个
i
将
接下来优化空间,滚动数组无法完全解决空间问题,
j,k
这两维难以缩小,考虑将
i
缩小到一维。如果要取走第
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=500005;
const int MOD=1000000007;
int n,d,A,p,a[N],f[11][1<<20];
inline void add(int&x,int y){x=x+y<MOD?x+y:x+y-MOD;}
inline void read(int&x){char c;while((c=getchar())<'0'||c>'9');x=c-'0';while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';}
int main(){
int i,j,k;
scanf("%d%d",&n,&d);
for(i=1;i<=n;++i)read(a[i]),A^=a[i];
sort(a+1,a+1+n);
f[0][0]=1;
for(p=i=1;i<=n;++i){
for(;p<=a[i];p<<=1);
for(k=p-1;~k;--k)f[d][k]=0;
for(j=d-1;~j;--j)for(k=p-1;~k;--k)add(f[j+1][k^a[i]],f[j][k]);
for(k=p-1;~k;--k)add(f[0][k],f[d][k]);
}
int ans=f[0][A];
if(n%d==0)ans=(ans-1+MOD)%MOD;
printf("%d",ans);
return 0;
}