BZOJ 2023 [Usaco2005 Nov]Ant Counting 数蚂蚁:dp【前缀和优化】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2023
题意:
有n个家族,共m只蚂蚁(n <= 1000, m <= 100000)。
每个家族有cnt[i]只蚂蚁,并且同一家族中的蚂蚁无差别。
从窝里爬出来x只蚂蚁的方案数为f(x)。
给定a,b,让你求 ∑ f(a to b) MOD 1000000。
题解:
表示状态:
dp[i][j] = combinations
i:第i个家族已经考虑过了
j:目前出来了j只蚂蚁
找出答案:
ans = ∑ dp[n][a to b]
如何转移:
dp[i][j] = ∑ dp[i-1][j-k] (0 <= k <= cnt[i], j-k >= 0)
即:dp[i][j] = ∑ dp[i-1][max(0,j-cnt[i]) to j];
边界条件:
dp[0][0] = 1
others = 0
优化:
(1)裸dp时间复杂度为O(n * m^2) = 10^13,绝对炸了。。。
所以前缀和优化:求 ∑ dp[i-1][max(0,j-cnt[i]) to j]。
(2)裸dp空间复杂度为 n*m(Byte) = 95 MB > 64 MB,又炸了咋办。。。
滚动数组。因为dp[i][j]只会用到dp[i-1][...]。
AC Code:
1 // state expression: 2 // dp[i][j] = combinations 3 // i: considering ith group 4 // j: j ants have been outside 5 // 6 // find the answer: 7 // sigma dp[n][a to b] 8 // 9 // transferring: 10 // dp[i][j] = sigma dp[i-1][j-k] (0 <= k <= cnt[i], j-k >= 0) 11 // 12 // boundary: 13 // dp[0][0] = 1 14 // others = 0 15 #include <iostream> 16 #include <stdio.h> 17 #include <string.h> 18 #define MAX_N 1005 19 #define MAX_M 100005 20 #define MOD 1000000 21 22 using namespace std; 23 24 int n,m,a,b; 25 int ans=0; 26 int cnt[MAX_N]; 27 int dp[2][MAX_M]; 28 int sum[2][MAX_M]; 29 30 void read() 31 { 32 cin>>n>>m>>a>>b; 33 memset(cnt,0,sizeof(cnt)); 34 int temp; 35 for(int i=0;i<m;i++) 36 { 37 cin>>temp; 38 cnt[temp]++; 39 } 40 } 41 42 int cal_mod(int x) 43 { 44 return (x%MOD+MOD)%MOD; 45 } 46 47 int cal_sum(int k,int x,int y) 48 { 49 if(x==0) return cal_mod(sum[k&1][y]); 50 return cal_mod(sum[k&1][y]-sum[k&1][x-1]); 51 } 52 53 void update_sum(int k,int x) 54 { 55 if(x==0) sum[k&1][x]=cal_mod(dp[k&1][x]); 56 else sum[k&1][x]=cal_mod(sum[k&1][x-1]+dp[k&1][x]); 57 } 58 59 void solve() 60 { 61 memset(dp,0,sizeof(dp)); 62 dp[0][0]=1; 63 for(int i=0;i<=m;i++) 64 { 65 sum[0][i]=1; 66 } 67 for(int i=1;i<=n;i++) 68 { 69 for(int j=0;j<=m;j++) 70 { 71 dp[i&1][j]=cal_sum(i-1,max(0,j-cnt[i]),j); 72 update_sum(i,j); 73 } 74 } 75 for(int i=a;i<=b;i++) 76 { 77 ans=cal_mod(ans+dp[n&1][i]); 78 } 79 } 80 81 void print() 82 { 83 cout<<ans<<endl; 84 } 85 86 int main() 87 { 88 read(); 89 solve(); 90 print(); 91 }