[USACO09MAR]牛飞盘队Cow Frisbee Team

题目 ::

农夫顿因开始玩飞盘之后,约翰也打算让奶牛们享受飞盘的乐趣.他要组建一只奶牛飞盘

队.他的N(1≤N≤2000)只奶牛,每只部有一个飞盘水准指数Ri(1≤Ri≤100000).约翰要选出1只或多于1只奶牛来参加他的飞盘队.由于约翰的幸运数字是F(1≤F≤1000),他希望所有奶牛的飞盘水准指数之和是幸运数字的倍数.

帮约翰算算一共有多少种组队方式.

输入格式

* Line 1: Two space-separated integers: N and F

* Lines 2..N+1: Line i+1 contains a single integer: R_i

输出格式

* Line 1: A single integer representing the number of teams FJ can choose, modulo 100,000,000.

输入输出样例

输入 #1
4 5 
1 
2 
8 
2 
输出 #1
3 

思路:::
比较像01背包;我们可以定义一个二维dp[i][j];表示前i头牛所选和为j(mod F)组合数;然后就是建立转移方程,对于每一头牛我们有两种操作
1):不选择该头牛,那么dp[i][j]=dp[i-1][j];
2): 选择该头牛,那我们就应该从前i-1头牛中找到所选和为(j-ma[i])的组合数
综上 转移方程::dp[i]j]+=dp[i-1][j]+dp[i-1][(j-ma[i])]
但需要注意一下(j-ma[i])可能为负的,(j-ma[i]+F)%F就可以变成正数了;
可别忘了初始化:
dp[i][ma[i]]=1;
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=1e8+5;
 5 const ll MOD=100000000;
 6 int ma[2005];
 7 int dp[2005][1005];
 8 int main()
 9 {
10     int n,F;
11     scanf("%d%d",&n,&F);
12     for(int i=1;i<=n;i++){
13         scanf("%d",&ma[i]);
14         ma[i]%=F;
15     }
16     for(int i=1;i<=n;i++)
17 
18     {
19         dp[i][ma[i]]=1;
20     }
21     for(int i=1;i<=n;i++)
22     {
23         for(int j=0;j<F;j++)
24         {
25             dp[i][j]=(dp[i][j]+dp[i-1][j]+dp[i-1][(j-ma[i]+F)%F])%MOD;;
26         }
27     }
28     printf("%d\n",dp[n][0]);
29     return 0;
30 }

 

但对于小数据 可以这样求(运行慢):(对于这题超内存,哈哈哈

题意就是求 各种组合数(1个,2个。。。。n个)

 1     int ant=0;
 2     deq[ant++]=0;
 3     for(int i=1;i<=n;i++)
 4     {
 5         int k=ant;
 6         for(int j=0;j<k;j++)
 7         {
 8             deq[ant++]=(deq[j]+a[i]);
 9         }
10     }
自己模拟一下你就明白了

 

 

推荐一个类似的题::https://codeforces.com/problemset/problem/1105/C

posted @ 2019-09-09 16:56  sj-_-js  阅读(360)  评论(0编辑  收藏  举报