[补题][Codeforces478D]Red-Green Towers(DP)

题目链接

http://codeforces.com/problemset/problem/478/D

题意

叠放塔:有红、绿两种色块。从第一层开始,第一层1块,第二层2块,第i层i块。
要求每一层只能用同一种颜色的块。
输入:红块和绿块数目
输出;能叠放出的最高高度h的塔的种数。定义塔某一层的颜色不同,则为不同种。

题解

状态表示

dp[i][j]表示i层的塔,使用了j个红块

转移方程

dp[i][j]=dp[i-1][j]+dp[i-1][j-i],当j>=i
dp[i][j]=dp[i-1][j],当j<i

需要get的点

  • 根据给出的数据范围,最高只有900左右,找到h。 一定满足h可以搭出来怎么证?
  • dp只需要两维,因为当塔的高度h固定,则给出使用的红块数,则使用的绿块数=h-红块数。
  • 计算当前层块数时,控制红块至少大于等于总块数-已有绿块数,这样保证了绿块是够的。
  • 初始化:dp[0][0]=1即可 ?
  • 滚动数组否则爆内存

代码

package Exam;

import java.util.Scanner;

public class FirstTest {
    public static void main(String args[]) {
        Scanner in=new Scanner(System.in);
        int r=in.nextInt();
        int g=in.nextInt();

        int MAXH=(int) Math.floor(Math.sqrt(2*(r+g))) ;
        int MAXR=(int) 2e5;
        int MOD=(int)1e9+7;

        int h=MAXH;
        while(h*(h+1)/2>r+g) {
            --h;
        }

        int[][] dp=new int[2][MAXR];
        dp[0][0]=1;
        for(int i=1;i<=h;++i) {
            for(int j=0;j<=r;++j) {
                if(j-i>=0) {
                    dp[i&1][j]=((dp[(i-1)&1][j])%MOD+(dp[(i-1)&1][j-i])%MOD)%MOD;
                }
                else {
                    dp[i&1][j]=(dp[(i-1)&1][j])%MOD;
                }
            }
        }

        int ans=0;
        for(int i=Math.max(0,h*(h+1)/2-g);i<=r;++i) {
            ans+=dp[h&1][i];
        }
        System.out.println(ans);
    }
}

原文地址:https://www.cnblogs.com/coding-gaga/p/10970726.html

时间: 2025-01-13 14:59:57

[补题][Codeforces478D]Red-Green Towers(DP)的相关文章

2020-3-14 acm训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019 解题报告+补题报告

2020-3-15比赛解题报告+2020-3-8—2020-3-15的补题报告 2020-3-15比赛题解 训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019  A建筑(模拟) 耗时:3ms 244KB 建筑 你哥哥在最近的建筑问题突破大会上获得了一个奖项 并获得了千载难逢的重新设计城市中心的机会 他最喜欢的城市奈梅根.由于城市布局中最引人注目的部分是天际线, 你的兄弟已经开始为他想要北方和东方的天际线画一些想法

4.30-5.1cf补题

//yy:拒绝转载!!! 悄悄告诉你,做题累了,去打两把斗地主就能恢复了喔~~~ //yy:可是我不会斗地主吖("'▽'") ~~~那就听两遍小苹果嘛~~~ 五一假期除了花时间建模,就抽空把最近没做的CF题补了点..毕竟明天开始又要继续上好多课呐...Yes, I can!(? •_•)?……(I can Huá shuǐ~~) codeforces 803 A. Maximal Binary Matrix   [简单构造] 题意:n行和n列填充零矩阵. 您要将k个1放在其中,使得得到

2018 HDU多校第三场赛后补题

2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube 题意: 在画布上画一个三维立方体. 题解: 模拟即可. 代码: #include <bits/stdc++.h> using namespace std; int a, b, c, R, C; char g[505][505]; int main () { int T; cin >>

20190303集训队选拔赛1补题报告

今天嘛,打得很糟糕,糟糕到什么程度呢,rank40 一共才55个人,我写了2题,总共尝试了5题,总共8题 写了3题及以上的有27个,剩下的都是2道和1道 小西瓜啊!!! 外因就不找了(其实也没有) 但是我知道有个原因非常重要:刷题量太少了 其他的不说了,再接再厉吧,刚才已经消沉了很久了,也放空了一会,所以开始补题吧 对了,集训队讲座补选上了(因为有的同学觉得太难退课了,感谢颜学长的劝退讲座,让我有机会一边修学分一边被虐) 这也意味着我要有一篇总结报告和三篇解题报告 解题报告要正儿八经地写 不能像

Codeforces VP/补题小记 (持续填坑)

Codeforces VP/补题小记 1149 C. Tree Generator 给你一棵树的括号序列,每次交换两个括号,维护每次交换之后的直径. ? 考虑括号序列维护树的路径信息和,是将左括号看做 \(-1\) ,右括号看做 \(1\) ,那么一段竖直向上的路径可以表示为括号序列的一个区间和,一段竖直向下的路径可以看做括号序列的一个区间和的相反数.我们要维护的是树的直径,也就是一段连续的和减去紧随其后的一段连续的差.具体来说就是 \[ \max_{\forall [l,r]}\{\sum_{

Codeforces Round #634 (Div. 3) 补题

A. Candies and Two Sisters 签到题,直接输出即可 代码 #include<bits/stdc++.h> #define INF 0x3f3f3f3f typedef long long ll; using namespace std; inline void read(int &p) { p=0;int flag=1;char c=getchar(); while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();} w

HDU 4908 (杭电 BC #3 1002题)BestCoder Sequence(DP)

题目地址:HDU 4908 这个题是从m开始,分别往前DP和往后DP,如果比m大,就比前面+1,反之-1.这样的话,为0的点就可以与m这个数匹配成一个子串,然后左边和右边的相反数的也可以互相匹配成一个子串,然后互相的乘积最后再加上就行了.因为加入最终两边的互相匹配了,那就说明左右两边一定是偶数个,加上m就一定是奇数个,这奇数个的问题就不用担心了. 代码如下: #include <iostream> #include <stdio.h> #include <string.h&g

[2015hdu多校联赛补题]hdu5371 Hotaru&#39;s problem

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371 题意:把一个数字串A翻过来(abc翻过来为cba)的操作为-A,我们称A-AA这样的串为N-sequence,现在给你一个数字串,问你这个串中最长的N-sequence子串长度 解:可以想到A-A是一个回文串,-AA也是一个回文串,那么首先Manacher跑一遍求出所有回文子串 可以想到任意两个互相覆盖的回文子串都可以表示成N-sequence 然后有三种搞法: 1.时间复杂度O(N*logN

2014多校第一场J题 || HDU 4870 Rating(DP || 高斯消元)

题目链接 题意 :小女孩注册了两个比赛的帐号,初始分值都为0,每做一次比赛如果排名在前两百名,rating涨50,否则降100,告诉你她每次比赛在前两百名的概率p,如果她每次做题都用两个账号中分数低的那个去做,问她最终有一个账号达到1000分需要做的比赛的次数的期望值. 思路 :可以直接用公式推出来用DP做,也可以列出210个方程组用高斯消元去做. (1)DP1:离散化.因为50,100,1000都是50的倍数,所以就看作1,2,20.这样做起来比较方便. 定义dp[i]为从 i 分数到达i+1