题意
问从序列里面取出一些数,使数字的和为F的倍数的方案数
思路
明显我们可以用某种凑的方式来满足条件,这很容易想到01背包
不过是方案数诶,那我们的背包就是要来统计答案
设(f(i,j))表示考虑到第(i)个数字,此时和模F的值为(j),这样设状态就十分好转移
f(i,j)=f(i,j)+f(i-1,j)+f(i-1,((j-a[i])%F+F)%F)
注意f(i,a[i])也是一种方案,所以设为1
代码
#include<bits/stdc++.h>
using namespace std;
int const MAXN=2010,MOD=1e8;
int n,F;
int r[MAXN],f[2][MAXN];
int main(){
scanf("%d%d",&n,&F);
for(int i=1;i<=n;i++){
scanf("%d",&r[i]);r[i]%=F;
}
int cur=0;
f[0][r[1]]=1;
for(int i=2;i<=n;i++){
cur^=1;
memset(f[cur],0,sizeof(f[cur]));
f[cur][r[i]]=1;
for(int j=0;j<=F-1;j++){
f[cur][j]=(f[cur][j]+f[cur^1][j]+f[cur^1][((j-r[i])%F+F)%F])%MOD;
//printf("%d ",f[cur][j%F]);
}
//printf("
");
}
printf("%d
",f[cur][0]);
return 0;
}
思考
明显的,这道题的01背包状态和别的不太一样,但是核心还是01背包的方法.不能只抓住表象,还是要运用其本质