当前位置: 代码迷 >> 综合 >> CF478D Red-Green Towers
  详细解决方案

CF478D Red-Green Towers

热度:27   发布时间:2024-02-23 08:56:30.0
考虑a+b的最优情况,那么最大层数刚好为:sqrt(2*(a+b))。
有可能由于a与b相差较大,则不能到达这个理论最大层数,但是没有关系,我们在dp过程中,保证当前每一步的转移是合法的,则最后倒序枚举合法的最大层数即可。
对于dp状态的解释,写在了注释中。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=4e5+5,MOD=1e9+7;
int a,b,n;
int f[2][N],sum[N];
signed main(){
    scanf("%lld%lld",&a,&b);n=sqrt(2*(a+b));f[0][0]=1;//假设第1层为1个,第2层为2个...//f[i][j]:前i层做完,共用了j个第一种颜色的方案数 //理论复杂度nlogn,但MOD常数较大,而我们发现,n个1e9加起来不会爆longlong//所以我们可以先全部累加后,再进行一次取模来卡常 for (register int i=1; i<=n; ++i){
    int m=min(i*(i+1)/2,a);for (register int j=0; j<=m; ++j){
    if (i<=j) f[i&1][j]+=f[(i-1)&1][j-i];if (i*(i+1)/2-j<=b) f[i&1][j]+=f[(i-1)&1][j];f[i&1][j]%=MOD;}for (register int j=0; j<=m; ++j) sum[i]+=f[i&1][j];sum[i]%=MOD;for (register int j=0; j<=m; ++j) f[(i-1)&1][j]=0;}for (register int i=n; i>=1; --i) if (sum[i]) {
    printf("%lld\n",sum[i]);break;	}
return 0;
}