列表

详情


JD23. 双色塔

描述

现在有红,绿两种颜色的石头,现在我们需要用这两种石头搭建一个塔,塔需要满足如下三个条件: 
1. 第 层应该包含1块石头,第2层应该包含两块,第 i 层需要包含 i 块石头。
2. 同一层的石头应该是同一个颜色(红或绿)。
3. 塔的层数尽可能多。 问在满足上面三个条件的前提下,有多少种不同的建造塔的方案,当塔中任意一个对应位置的石头颜色不同,我们就认为这两个方案不相同。石头可以不用完。

数据范围:红绿颜色石头数量满足 ,  

输入描述

输入仅包含两个正整数,分别表示红和绿砖块的数量a,b。

输出描述

输出和仅包含一个正整数,表示不同的方案数对1000000007取模的结果。

示例1

输入:

4 6

输出:

2

说明:

从底到顶颜色可以是 红、绿、红、绿 或 绿、绿、绿、红

原站题解

C++ 解法, 执行用时: 68ms, 内存消耗: 1912KB, 提交时间: 2021-05-13

//
// Created by kumo on 2021/5/12.
//

#include <cstdio>
#include <algorithm>
#include <iostream>
#define MOD 1000000007

using namespace std;

int dp[2][200005] = {0};

int main() {
    int a, b;
    scanf("%d%d", &a, &b);
    if (a > b) {
        int c = a;
        a = b;
        b = c;
    }
    dp[0][1] = 1, dp[0][0] = 1;
    int total = 3;
    int least = max(total - b, 0);
    int most = min(total, a);
    int last = 0;
    int now = 1;
    int cur = 2;
    while (most >= least) {
        // cout << "most / least: " << most << " / " << least << endl;
        for (int i = 0; i < least; i++) {
            dp[now][i] = 0;
        }
        for (int i = least; i < cur; i++) {
            dp[now][i] = dp[last][i];
        }
        for (int i = cur; i <= most; i++) {
            dp[now][i] = (dp[last][i - cur] + dp[last][i]) % MOD;

            // cout << "dp[0], dp[1], result: " << dp[now][i] << ", " << dp[last][i - cur] << ", " << dp[last][i] << endl;
        }
        cur++;
        total += cur;
        least = max(total - b, 0);
        most = min(total, a);
        last = 1 - last;
        now = 1 - now;
    }
    total -= cur;
    cur--;
    least = max(total - b, 0);
    most = min(total, a);
    int sum = 0;
    for (int i = least; i <= most; i++) {
        sum = (sum + dp[last][i]) % MOD;
    }
    cout << sum << endl;
    return 0;
}

C++ 解法, 执行用时: 70ms, 内存消耗: 2716KB, 提交时间: 2021-07-02

#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
#define MOD 1000000007
void GetCount(int a,int b)
{
    if(a==0||b==0)
    {
        cout<<1<<endl;
        return;
    }
    //dp[i][j],i表示第i层,j表示石头个数,dp表示不同放置方式的个数
    vector<vector<int>>dp(2,vector<int>(200000,0));
    int level=sqrt(2*(a+b));
    //假设红宝石个数最少
    if(a>b)
        swap(a,b);
    int sum=1;//一共需要的石头个数
    int upper,lower,cur,last;
    dp[1][0]=dp[1][1]=1;
    for(int i=2;i<=level;++i)
    {
        sum+=i;
        int redupper=min(a,sum);//红宝石的上限
        //如果绿宝石b填补完前i层且sum-b>0,那么前i层至少需要sum-b个红宝石填充
        int redlower=max(sum-b,0);//红宝石下限
        if(redlower>redupper)
            break;
        upper=redupper;
        lower=redlower;
        cur=i&1;
        last=!cur;
        for(int j=lower;j<i;++j)
        {
            //由于前i层的红宝石个数少于
            dp[cur][j]=dp[last][j];
        }
        for(int j=i;j<=upper;++j)
        {
            dp[cur][j]= (dp[last][j] + dp[last][j - i]) % MOD;
        }
    }
    int res=0;
    for (int j = lower; j <= upper; j++) 
    {
        res = (res + dp[cur][j]) % MOD;
    }
    cout << res << endl;
}
int main()
{
    int a,b;
    cin>>a>>b;
    GetCount(a, b);
    return 0;
}

上一题