题目大意:
有编号一到t的蚂蚁家族,每个家族有不同的蚂蚁数。
问构成S只蚂蚁到构成B只蚂蚁共有多少种方式
例如
While observing one group, the set of three ant families was seen as {1, 1, 2, 2, 3}, though rarely in that order. The possible sets of marching ants were:
3 sets with 1 ant: {1} {2} {3}
5 sets with 2 ants: {1,1} {1,2} {1,3} {2,2} {2,3}
5 sets with 3 ants: {1,1,2} {1,1,3} {1,2,2} {1,2,3} {2,2,3}
3 sets with 4 ants: {1,2,2,3} {1,1,2,2} {1,1,2,3}
1 set with 5 ants: {1,1,2,2,3}
Input
* Lines 2..A+1: Each line contains a single integer that is an ant type present in the hive
Output
Sample Input
3 5 2 3 1 2 2 1 3
Sample Output
10
这道题用母函数来求解。
所谓母函数,就是生成函数,说白了就是多项相乘,每一项分别表示每个家族里取一只,两只,三只。。。
最后乘出的结果中,x的n次方的系数就表示构成n个蚂蚁有多少种方式
代码如下
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #define M 1000000 5 int cnt[1002] = {0}; 6 int c1[100002] = {0}; 7 int c2[100002] = {0}; 8 int ans[100002] = {0}; 9 int n; 10 11 void multi(int cn1, int cn2) { 12 for(int i = 0; i <= cn1; i++) { 13 for(int j = 0; j <= cn2; j++) { 14 ans[i+j] = (ans[i+j] + c1[i]*c2[j])%M; 15 } 16 } 17 n = cn1 + cn2; 18 } 19 20 int main(int argc, char const *argv[]) 21 { 22 //freopen("input.txt","r",stdin); 23 int t, s, a, b; 24 scanf("%d %d %d %d",&t, &a, &s, &b); 25 for(int i = 0; i < a; i++) { 26 int tmp; 27 scanf("%d",&tmp); 28 cnt[tmp]++; 29 } 30 for(int i = 0; i <= cnt[1];i++) { 31 ans[i] = 1; 32 } 33 n = cnt[1]; 34 for(int i = 2; i <= t; i++) { 35 memset(c1, 0, sizeof(c1)); 36 memset(c2, 0, sizeof(c2)); 37 for(int j = 0; j <= n; j++) { 38 c1[j] = ans[j]; 39 } 40 for(int j = 0; j <= cnt[i]; j++) { 41 c2[j] = 1; 42 } 43 memset(ans, 0, sizeof(ans)); 44 multi(n,cnt[i]); 45 } 46 int ansm = 0; 47 for(int i = s; i <= b; i++) { 48 ansm = (ansm + ans[i])%M; 49 } 50 printf("%d\n",ansm); 51 return 0; 52 }
注意,此题要求输出后六位,要mod M
此题也可以用动态规划法求解
dp[i][j]表示前i个家族构成j的方法数
那么
dp[i][j] = dp[i-1][j-k](k..0 to min(j,c[i]));
上面的式子可写为
dp[i][j] = dp[i][j-1] + dp[i-1][j]-dp[i][j-1-c[i]];
代码如下
1 /*dp[i][j] means i to j geshu 2 3 dp[i][j] = dp[i-1][j-k](k..0 to min(j,c[i])); 4 dp[i][j] = dp[i][j-1] + dp[i-1][j]-dp[i][j-1-c[i]]; 5 6 }*/ 7 8 9 #include <cstdio> 10 #include <cstdlib> 11 #include <cstring> 12 #define M 1000000 13 int cnt[1002] = {0}; 14 int dp[1002][100002] = {0}; 15 16 17 int main(int argc, char const *argv[]) 18 { 19 freopen("input.txt","r",stdin); 20 int t, s, a, b; 21 scanf("%d %d %d %d",&t, &a, &s, &b); 22 for(int i = 0; i < a; i++) { 23 int tmp; 24 scanf("%d",&tmp); 25 cnt[tmp]++; 26 } 27 28 for(int i = 0; i <= t; i++) { 29 dp[i][0] = 1; 30 } 31 32 for(int i = 0; i < t; i++) { 33 for(int j = 1; j <= b; j++) { 34 if(j-1-cnt[i+1] >= 0) { 35 dp[i+1][j] = (dp[i+1][j-1] + dp[i][j]-dp[i][j-1-cnt[i+1]] + M ) % M; 36 } 37 else { 38 dp[i+1][j] = (dp[i+1][j-1] + dp[i][j])%M; 39 } 40 } 41 } 42 43 int ansm = 0; 44 for(int i = s; i <= b; i++) { 45 ansm = (ansm + dp[t][i] + M)%M; 46 } 47 printf("%d\n",ansm); 48 return 0; 49 }