Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 3 Accepted Submission(s) : 2
Being a bit mathematical, Bessie started wondering. Bessie noted that the hive has T (1 <= T <= 1,000) families of ants which she labeled 1..T (A ants altogether). Each family had some number Ni (1 <= Ni <= 100) of ants.
How many groups of sizes S, S+1, ..., B (1 <= S <= B <= A) can be formed?
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}
Your job is to count the number of possible sets of ants given the data above.
分析:
多重集组合数也是由多重背包问题拓展出来的一类经典问题。这里仍然给大家讲2种方法:
①朴素方法:
状态:dp[i][j]:前i种中选j个可以组成的种数
决策:第i种选k个,k<=ant[i] && j-k>=0
转移:dp[i][j]=Σdp[i-1][j-k]
复杂度为O(B*Σant[i])即O(B*A)也即O(A^2),虽说这题A最大可到1e5,但是实际数据水,能过
②优化递推式
状态:dp[i][j]:前i种中选j个可以组成的种数
决策:第i种不选或者至少选一个
转移:
1.若不选,显然为dp[i-1][j]
2.若至少选一种,那么为dp[i][j-1]-dp[i-1][j-ant[i]-1]
我们这样来理解,dp[i][j-1] 理解为已经选了第i种一个,至于还选不选这里我们不管它,所以它可以用来代表至少选一个
但是dp[i][j-1]还有一层含义便是前i种中选j-1个可以组成的种数,所以它包含了选ant[i]个第i种,即dp[i-1][j-ant[i]-1],但
dp[i][j] 最多选ant[i]个第i种,所以最后要减去这一种。
所以 dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-ant[i]-1]
复杂度为O(T*B)


1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 const int mod = 1000000; 7 int dp[1005][100005]; 8 int main() 9 { 10 int ant[1005]; 11 int t, a, s, b; 12 cin >> t >> a >> s >> b; 13 memset(ant, 0, sizeof(ant)); 14 int i; 15 int j; 16 for (i = 1; i <= a; i++) 17 { 18 cin >> j; 19 ant[j]++; 20 } 21 for (i = 0; i <= t; i++) dp[i][0] = 1; 22 dp[0][0] = dp[1][0] = 1; 23 for (i = 1; i <= t; i++) 24 { 25 for (j = 1; j <= b; j++) 26 { 27 if (j - ant[i] - 1 >= 0) 28 {//在取模时若出现了减法运算则需要先+Mod再对Mod取模,防止出现负数(如5%4-3%4为负数) 29 dp[i][j] = (dp[i - 1][j] + dp[i ][j - 1] - dp[i - 1][j - ant[i] - 1] + mod) % mod; 30 } 31 else 32 { 33 dp[i][j] = (dp[i - 1][j] + dp[i][j - 1])%mod; 34 } 35 } 36 } 37 int sum = 0; 38 for (i = s; i <= b; i++) 39 sum = (sum + dp[t][i]) % mod; 40 cout << sum << endl; 41 return 0; 42 }
为了节约空间%2;


#include<iostream> using namespace std; #define MOD 1000000 int T, A, S, B; int ant[1005]; int dp[2][100000]; int ans; int main() { scanf("%d%d%d%d", &T, &A, &S, &B); for (int i = 1; i <= A; i++) { int aa; scanf("%d", &aa); ant[aa]++; } dp[0][0] = dp[1][0] = 1; for (int i = 1; i <= T; i++) for (int j = 1; j <= B; j++) if (j - ant[i] - 1 >= 0) dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1] - dp[(i - 1) % 2][j - ant[i] - 1] + MOD) % MOD; //在取模时若出现了减法运算则需要先+Mod再对Mod取模,防止出现负数(如5%4-3%4为负数) else dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1]) % MOD; for (int i = S; i <= B; i++) ans = (ans + dp[T % 2][i]) % MOD; printf("%d\n", ans); return 0; }
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 3 Accepted Submission(s) : 2
Being a bit mathematical, Bessie started wondering. Bessie noted that the hive has T (1 <= T <= 1,000) families of ants which she labeled 1..T (A ants altogether). Each family had some number Ni (1 <= Ni <= 100) of ants.
How many groups of sizes S, S+1, ..., B (1 <= S <= B <= A) can be formed?
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}
Your job is to count the number of possible sets of ants given the data above.
分析:
多重集组合数也是由多重背包问题拓展出来的一类经典问题。这里仍然给大家讲2种方法:
①朴素方法:
状态:dp[i][j]:前i种中选j个可以组成的种数
决策:第i种选k个,k<=ant[i] && j-k>=0
转移:dp[i][j]=Σdp[i-1][j-k]
复杂度为O(B*Σant[i])即O(B*A)也即O(A^2),虽说这题A最大可到1e5,但是实际数据水,能过
②优化递推式
状态:dp[i][j]:前i种中选j个可以组成的种数
决策:第i种不选或者至少选一个
转移:
1.若不选,显然为dp[i-1][j]
2.若至少选一种,那么为dp[i][j-1]-dp[i-1][j-ant[i]-1]
我们这样来理解,dp[i][j-1] 理解为已经选了第i种一个,至于还选不选这里我们不管它,所以它可以用来代表至少选一个
但是dp[i][j-1]还有一层含义便是前i种中选j-1个可以组成的种数,所以它包含了选ant[i]个第i种,即dp[i-1][j-ant[i]-1],但
dp[i][j] 最多选ant[i]个第i种,所以最后要减去这一种。
所以 dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-ant[i]-1]
复杂度为O(T*B)


1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 const int mod = 1000000; 7 int dp[1005][100005]; 8 int main() 9 { 10 int ant[1005]; 11 int t, a, s, b; 12 cin >> t >> a >> s >> b; 13 memset(ant, 0, sizeof(ant)); 14 int i; 15 int j; 16 for (i = 1; i <= a; i++) 17 { 18 cin >> j; 19 ant[j]++; 20 } 21 for (i = 0; i <= t; i++) dp[i][0] = 1; 22 dp[0][0] = dp[1][0] = 1; 23 for (i = 1; i <= t; i++) 24 { 25 for (j = 1; j <= b; j++) 26 { 27 if (j - ant[i] - 1 >= 0) 28 {//在取模时若出现了减法运算则需要先+Mod再对Mod取模,防止出现负数(如5%4-3%4为负数) 29 dp[i][j] = (dp[i - 1][j] + dp[i ][j - 1] - dp[i - 1][j - ant[i] - 1] + mod) % mod; 30 } 31 else 32 { 33 dp[i][j] = (dp[i - 1][j] + dp[i][j - 1])%mod; 34 } 35 } 36 } 37 int sum = 0; 38 for (i = s; i <= b; i++) 39 sum = (sum + dp[t][i]) % mod; 40 cout << sum << endl; 41 return 0; 42 }
为了节约空间%2;


#include<iostream> using namespace std; #define MOD 1000000 int T, A, S, B; int ant[1005]; int dp[2][100000]; int ans; int main() { scanf("%d%d%d%d", &T, &A, &S, &B); for (int i = 1; i <= A; i++) { int aa; scanf("%d", &aa); ant[aa]++; } dp[0][0] = dp[1][0] = 1; for (int i = 1; i <= T; i++) for (int j = 1; j <= B; j++) if (j - ant[i] - 1 >= 0) dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1] - dp[(i - 1) % 2][j - ant[i] - 1] + MOD) % MOD; //在取模时若出现了减法运算则需要先+Mod再对Mod取模,防止出现负数(如5%4-3%4为负数) else dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1]) % MOD; for (int i = S; i <= B; i++) ans = (ans + dp[T % 2][i]) % MOD; printf("%d\n", ans); return 0; }