BZOJ 3400 [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队:dp【和为f的倍数】

题目链接:http://begin.lydsy.com/JudgeOnline/problem.php?id=1375

题意:

  给你n个数,你可以从中选任意多个,但不能不选。问你所选数字之和为f的倍数的方案数。

 

题解:

  表示状态:

    dp[i][j] = num of ways

    i:考虑到第i个数(还没选)

    j:之前所选数之和 MOD f == j

 

  找出答案:

    ans = dp[n][0] - 1

    不选也是一种方案,但题目种要求不能不选,所以-1。

 

  如何转移:

    选或不选第i个数。

    dp[i+1][j] += dp[i][j] (不选)

    dp[i+1][(j+r[i])%f] += dp[i][j] (选)

 

  边界条件:

    dp[0][0] = 1 (什么都不选也是一种方案)

    others = 0

 

AC Code:

 1 // state expression:
 2 // dp[i][j] = num of ways
 3 // i: considering ith cow
 4 // j: sum MOD f == j
 5 //
 6 // find the answer:
 7 // dp[n][0]
 8 //
 9 // transferring:
10 // now: dp[i][j]
11 // dp[i+1][j] += dp[i][j]
12 // dp[i+1][(j+r[i])%f] += dp[i][j]
13 //
14 // boundary:
15 // dp[0][0] = 1
16 // others = 0
17 #include <iostream>
18 #include <stdio.h>
19 #include <string.h>
20 #define MAX_N 2005
21 #define MAX_F 1005
22 #define MOD 100000000
23 
24 using namespace std;
25 
26 int n,f;
27 int r[MAX_N];
28 int dp[MAX_N][MAX_F];
29 
30 void read()
31 {
32     cin>>n>>f;
33     for(int i=0;i<n;i++)
34     {
35         cin>>r[i];
36     }
37 }
38 
39 void solve()
40 {
41     memset(dp,0,sizeof(dp));
42     dp[0][0]=1;
43     for(int i=0;i<n;i++)
44     {
45         for(int j=0;j<f;j++)
46         {
47             dp[i+1][j]=(dp[i+1][j]+dp[i][j])%MOD;
48             dp[i+1][(j+r[i])%f]=(dp[i+1][(j+r[i])%f]+dp[i][j])%MOD;
49         }
50     }
51 }
52 
53 void print()
54 {
55     cout<<((dp[n][0]-1)%MOD+MOD)%MOD<<endl;
56 }
57 
58 int main()
59 {
60     read();
61     solve();
62     print(); 
63 }

 

posted @ 2017-09-20 22:11  Leohh  阅读(170)  评论(0编辑  收藏  举报