/*
给定r个红块,g个绿块,按要求堆放
问当堆放成最大高度时,有多少种可能的堆放方式
排列要求:1.第i行放i块
2.每行同色
首先当然要确定能够放置几行
设红块有r个,绿块有g个,那么放置h行需要(h+1)h/2个
那么r+g>=(h+1)h/2 => 2(r+g)>=(h+1)h => 2(r+g)>h*h
那么有 h=sqrt(2r+2g),然后再找符合条件的h
然后确定状态:dp[i][j]表示前i行用了j个红块的排列方案
转移方程:外层循环枚举i表示第i层,内层循环枚举j表示红块使用数
dp[i][j]=dp[i-1][j]+dp[i-1][j-i],即该行不用红块和用红块的两种决策
决策合法性:当j<i时这层只能用绿块
同时第i层红块至少用max(i(i+1)/2-g,0)个
初始状态,dp=0,r>0,dp[1][1]=1,g>0,dp[1][0]=1
用滚动数组优化
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll ans,h,dp[200005],r,g;
#define mod 1000000007
int main(){
cin>>r>>
g;
h=sqrt(
2*r+
2*
g);
while(h*(h+
1)/
2>(r+g))h--
;
if(r>
0)dp[
1]=
1;
if(g>
0)dp[
0]=
1;
for(
int i=
2;i<=h;i++
){
int l=max((ll)
0,(i+
1)*i/
2-
g);
for(
int j=r;j>=l;j--
){
if(j>=i)dp[j]=(dp[j]+dp[j-i])%
mod;
else dp[j]=dp[j];
//只能用绿块
}
}
int l=max((ll)
0,(h+
1)*h/
2-
g);
for(
int i=r;i>=l;i--
)
ans=(ans+dp[i])%
mod;
cout<<ans<<
endl;
}
转载于:https://www.cnblogs.com/zsben991126/p/10475254.html
相关资源:各显卡算力对照表!