题目链接:
http://codeforces.com/problemset/problem/478/D
题意:
有红绿两色的方块,数量分别为r个和g个。有0<=r,g<=2e5,r+g>=1
我们想用这红绿两色的方块(不一定全部,可以是一部分),构成一个高度尽可能高的积木块。
这个积木块需要满足——
1,假设高度为h,那么第一层有1个,第二层有2个,……,第h层有h个。
2,每层方块的颜色,不是全部为红色,就是全部为绿色。
让你输出,有多少种方案,可以构成高度最高的积木块。
思路:
http://blog.csdn.net/snowy_smile/article/details/50266509
dp[i][j]:=摆成高度为i的,红块还有j个剩余 的方案数
转移:
if(j+i<=r) dp[i][j] = dp[i][j]+dp[i-1][j+i]
if(green >= i) dp[i][j] = dp[i][j]+dp[i-1][j] : 如果剩下的绿块够摆第i层,可以不用红块,可转移
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 ////////////////////////////////////////////////////////////////////////// 16 const int maxn = 2e5+10; 17 const int mod = 1e9+7; 18 19 int r,g; 20 int dp[2][maxn]; 21 22 int main(){ 23 cin >> r >> g; 24 int top = 900; 25 while(top*(top+1) > 2*(r+g)) top--; 26 int now = 0, pre = 1; 27 dp[now][r] = 1; 28 for(int i=1; i<=top; i++){ 29 swap(now,pre); 30 MS(dp[now]); 31 for(int j=0; j<=r; j++){ 32 if(j+i<=r) dp[now][j] = (dp[now][j]+dp[pre][j+i])%mod; 33 int t = g-((i-1)*i/2-(r-j)); 34 if(t >= i) dp[now][j] = (dp[now][j]+dp[pre][j])%mod; 35 } 36 } 37 int ans = 0; 38 for(int i=0; i<=r; i++){ 39 ans = (ans+dp[now][i])%mod; 40 } 41 cout << ans << endl; 42 43 return 0; 44 }