hackerrank【Lego Blocks】:计数类dp

题目大意:

修一个层数为n,长度为m的墙,每一层可以由长度为1、2、3、4的砖块构成。

每一层都在同一个长度处出现缝隙是方案非法的,问合法的方案数有多少种

思路:

先求出总方案,再减去所有非法的方案数

总方案数容易求得,略

非法方案数就不太好求了,由于需要判重,我们可以按照 " 最左边的缝隙 " 所在的位置给非法方案数分类

这样就不会有重复了!

具体见代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
#define mod 1000000007
long long n,m;
long long dp[1010],a[1010],sum[1010];
long long pow(long long a,long long b)
{
    long long res=1;
    while(b)
    {
        if(b&1)
        {
            res*=a;
            res%=mod;
        }
        a*=a;
        a%=mod;
        b>>=1;
    }
    return res;
}
void solve(long long n,long long m)
{
    a[1]=1;
    a[2]=2;
    a[3]=4;
    a[4]=8;
    for(int i=5;i<=n;i++)
    {
        a[i]=(a[i-1]+a[i-2]+a[i-3]+a[i-4])%mod;
    }
    for(int i=1;i<=n;i++)
    {
        sum[i]=pow(a[i],m);
    }
    dp[0]=0;
    for(int i=1;i<=n;i++)
    {
        dp[i]=sum[i];
        for(int j=1;j<i;j++)
        {
            dp[i]-=dp[j]*sum[i-j];
            dp[i]=(dp[i]%mod+mod)%mod;
        }
    }
    cout<<dp[n]<<endl;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>n>>m;
        solve(m,n);
    }
    return 0;
}
时间: 2024-11-09 02:47:31

hackerrank【Lego Blocks】:计数类dp的相关文章

CH5E26 扑克牌 (计数类DP)

\(CH~5E26~*~\)扑克牌: (计数类DP) \(solution:\) 唉,计数类DP总是这么有套路,就是想不到. 这道题我们首先可以发现牌的花色没有价值,只需要知道每种牌有 \((0,4]\) 张,牌的面值也不用管,只需要知道总共有 \((0,13]\) 种牌.然后我们就可以设出状态: \(f[i][j][p][q]\) 表示还剩 \(1\) 张有 \(i\) 种牌的,还剩 \(2\) 张牌的有 \(j\) 种,还剩 \(3\) 张牌的有 \(p\) 种,还剩 \(4\) 张牌的有

$Poj1737\ Connected\ Graph$ 计数类$DP$

AcWing Description 求$N$个节点的无向连通图有多少个,节点有标号,编号为$1~N$. $1<=N<=50$ Sol 在计数类$DP$中,通常要把一个问题划分成若干个子问题,以便于执行递推. 一个连通图不容易划分,而一个不连通的无向图则很容易划分成结点更少的两部分.所以我们把问题转化成用$N$个点的无向图总个数减去$N$个点的不连通无向图的个数. $N$个点的无向图总个数显然是$2^{N*(N-1)/2}$,还是简单说下叭,就是$N$个点连成完全图的边数显然是$N*(N-1)

0x50 动态规划(0x5C 计数类DP)例题3:装饰围栏(题解)(计数类DP讲解,确定第k个排列)

计数类DP一般就是确定DP状态,DP出排名范围,然后不断逼近. 题意 题目链接 [题目描述] 有 N 块长方形的木板,长度分别为1,2,-,N,宽度都是1. 现在要用这 N 块木板组成一个宽度为 N 的围栏,满足在围栏中,每块木板两侧的木板要么都比它高,要么都比它低. 也就是说,围栏中的木板是高低交错的. 我们称"两侧比它低的木板"处于高位,"两侧比它高的木板"处于低位. 显然,有很多种构建围栏的方案. 每个方案可以写作一个长度为N的序列,序列中的各元素是木板的长度

HackerRank - &quot;Lego Blocks&quot;

A combination of different DP passes. https://www.hackerrank.com/challenges/lego-blocks/editorial #include <iostream> #include <vector> #include <cstring> using namespace std; typedef unsigned long long ULL; const ULL mod = 1000000007; U

codeforces 277.5 div2 F:组合计数类dp

题目大意: 求一个 n*n的 (0,1)矩阵,每行每列都只有两个1 的方案数 且该矩阵的前m行已知 分析: 这个题跟牡丹江区域赛的D题有些类似,都是有关矩阵的行列的覆盖问题 牡丹江D是求概率,这个题是方案数,也比较相似.. 这种题中,因为只要求方案数..我们只要关注几行几列有几个1,而不必要关注具体的位置 题解: 行列都需要处理,因此考虑记录列的状态,然后一行一行的转移 最暴力的方程: dp[i][j][k][t] 表示已经确定了 i 行 有 j列已经有两个1,有k列只有一个1,有t列一个1也没

AcWing 306. 杰拉尔德和巨型象棋 计数类DP

参考秦大佬的题解: https://www.acwing.com/solution/AcWing/content/1730/ //通过容斥原理 //那么F[i]表示为从左上角走到第i个黑色格子,而且途中不经过其他黑色格子的方案数 //终点作为第k+1个黑格子 //F[i]=(1,1)到(xi,xj)的总方案数-前(i-1)黑格方案数*黑格到(xi,yi)的方案数 //其中, (1,1)到(xi,xj)的总方案数为C(xi-1+yi-1,xi-1) #include<iostream> #inc

计数类问题专题

主要是前两天被uoj的毛爷爷的题虐的不轻,心里很不爽啊,必须努力了,, 计数类问题分为:1.组合数学及数论计数 2.dp:状态压缩dp,插头轮廓线dp,树形dp,数位dp,普通dp 3.容斥原理 4.polya原理 5.图论计数 6.生成函数 7.其它(生成树计数等等) 本文主要研究前3个内容 考虑基本计数原理:加法原理,减法原理,乘法原理,除法原理 计数的基本原则:结果不重不漏 加法原理比较自然,中间过程有时减法原理 考虑到无向,有向图的各种量值(生成树之类)计数,状态压缩dp解决 论文:ht

51 nod 1610 路径计数(Moblus+dp)

1610 路径计数 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 路径上所有边权的最大公约数定义为一条路径的值. 给定一个有向无环图.T次修改操作,每次修改一条边的边权,每次修改后输出有向无环图上路径的值为1的路径数量(对1,000,000,007取模). Input 第一行两个整数n和m,分别表示有向无环图上的点数和边数.(1<=n<=100,1<=m<=50,000) 第2~m+1行每行三个数x,y,z,表示有一条从x到y权值为z的边.(1

Blocks题解(区间dp)

Blocks题解 区间dp 阅读体验...https://zybuluo.com/Junlier/note/1289712 很好的一道区间dp的题目(别问我怎么想到的) dp状态 其实这个题最难的地方是这道题目的状态怎么设 首先既然是区间dp,那肯定最先想到的状态是 $dp[i][j]$表示消掉区间$[i,j]$上所有的块的最大分数 突然发现这个状态会受区间外和$i$或$j$颜色相同的块的影响 并且转移也并不好转移=_= 所以我们考虑换一种状态... 既然说会受到外面的块的影响?那考虑一种方法来