洛谷 P2946 [USACO09MAR] Cow Frisbee Team S 题解
题目大意
洛谷 P2946 [USACO09MAR] Cow Frisbee Team S
给定序列 \(r_{[1..n]}\),求选出其中至少 \(1\) 个元素使所有元素的总和是 \(f\) 的倍数的方案数对 \(10^8\) 取模的值。
思路分析
这是一道特殊的 0-1 背包。由于它要求总和是 \(f\) 的倍数,即余数为 \(0\),所以我们可以将每个元素的值都模上 \(f\),则所有余数相加再模上 \(f\) 余数为 \(0\) 即可。此时背包容量为 \(f\),则状态转移方程为:
\[dp_{i,j}=dp_{i-1,j}+dp_{i-1,g(j,a_i)}
\]
其中 \(g(x,y)=(x-y+f) \bmod f,a_i=r_i\bmod f\)。
代码呈现
#include<bits/stdc++.h>
using namespace std;
const int N=2010,F=1010,mod=1e8;
int n,f;
int r[N],dp[N][F];
int main(){
scanf("%d%d",&n,&f);
for (int i=1;i<=n;++i) scanf("%d",r+i);
dp[0][0]=1; // 都不选
for (int i=1;i<=n;++i){
for (int j=0;j<f;++j) dp[i][j]=(dp[i-1][j]+dp[i-1][(j+f-r[i]%f)%f])%mod;
}
printf("%d",dp[n][0]-1); // 减去都不选
return 0;
}

浙公网安备 33010602011771号