洛谷 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;
}
posted @ 2025-12-14 17:10  CodingJuRuo  阅读(1)  评论(0)    收藏  举报