标签:http io os ar for sp on amp ef
题目链接:点击打开链接
题意:
给定r个红色正方体,g个绿色正方体。
要求搭建一个高度为n的塔。
对于高度为n的塔,第一层积木个数必须为n,第二层必须为n-1,依次类推,每层比下面那层少一个。
且同一层颜色必须相同。
问:
我们设最高能搭建的塔的高度为h,问有多少种方法能搭建出高度为h的塔。
思路:
从最顶层开始构造。
设dp[i][j]表示前i层花了j个红色木块的方法数
因为每层的个数固定,所以知道花费红色的个数,则就能马上算出花费绿色的个数。
而且对于最高的高度,是和颜色无关的,只和r+g有关,YY得证。
或者直接dp上去,当这一次的方案数是0时,则上一次就是最高的高度了。
前i层可以用滚动数组优化掉。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <map>
#include <cmath>
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if(x>9) pt(x/10);
putchar(x%10+'0');
}
using namespace std;
typedef long long ll;
#define N 200010
const ll mod = 1e9+7;
ll r, g;
ll dp[2][N]; // dp[cur][i][j]表示剩下i个红色,j=0最后一层是红色
bool vis[N];
vector<ll>G[2];
ll ok(){
int cur = 0;
memset(dp[cur], 0, sizeof dp[cur]);
dp[cur][0] = 1;
ll sum = 0;
for(ll i = 0; ; i ++){
cur ^= 1;
sum += i;
if( sum > r+g) break;
memset(dp[cur], 0, sizeof dp[cur]);
for(int j = 0; j <= r && j <= sum; j++)
{
if(sum - j + (i+1) <= g)
dp[cur][j] += dp[cur^1][j], dp[cur][j] %= mod;
if(j+(i+1)<=r)
dp[cur][j+i+1] += dp[cur^1][j], dp[cur][j+i+1] %= mod;
}
}
ll ans = 0;
for(int i = 0; i <= r; i++){
ans += dp[cur][i];
if(ans >= mod) ans %= mod;
}
return ans;
}
int main() {
while(cin>>r>>g){
cout<<ok()<<endl;
}
return 0;
}Codeforces 478D Red-Green Towers dp
标签:http io os ar for sp on amp ef
原文地址:http://blog.csdn.net/qq574857122/article/details/40190765