[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 }
自己模拟一下你就明白了
纵使单枪匹马,也要勇闯天涯