今天第一次写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;
}
本文介绍了一种通过优化动态规划(DP)方法解决特定异或和问题的技巧。该问题要求选取若干堆使剩余堆的异或和为0。文章首先介绍了朴素的DP方法及其时间复杂度,随后提出了通过排序和位操作来减少时间复杂度的方法,并通过调整DP的状态设计和顺序进一步优化空间复杂度。
754

被折叠的 条评论
为什么被折叠?



