[省选] [DP] HLOI2015 Color

来源:互联网 发布:淘宝正品潮牌店铺 编辑:程序博客网 时间:2024/05/21 06:36

Description 题目描述

魔法世界的庆典就要到了,大法师交给Chavo好多好多魔法丝带,要求Chavo为它们涂上五彩斑斓的颜色。Chavo把一条丝带等分成m段,将连续的几段涂上一种颜色。她有n种不同颜色的颜料,而且她会使用每一种颜色一次且仅一次。某一次涂色可能会覆盖掉之前已经涂上的颜色,但是她不会让一种颜色完全覆盖掉另外一种颜色。现在Chavo想知道,她有多少种不同的方案为一条丝带涂色?结果要对1000000007取模后输出。
设颜色A的起点为L1,终点为R1,颜色B的起点为L2,终点为R2,当L1L2R2R1时,颜色A完全覆盖颜色B。每一种方案包含nLiRi,每一对LiRi代表一次涂色的起点和终点(1LiRim)。
两种方案不一样当且仅当一种方案里的某一次涂色的起点和终点在另外一种方案里不存在。

Input 输入

只有一行输入整数nm

Output 输出

输出一行带有一个整数代表有多少种画法满足题意,结果要对1000000007取模后输出。

Sample Input 样例输入

2 3

Sample Output 样例输出

6

Limits 限制

对于30%的数据,1n,m10
对于60%的数据,1n,m100
对于100%的数据,1nm100000
Time Limit : 2s & Memory Limit : 128MB

Hints 提示

6种情况为
这里写图片描述

由题意可知,对于任意两段颜色来说,设起点分别为L1,L2,终点分别为R1,R2
L1=L2,则无论R1,R2大小关系如何,必定一段颜色覆盖另一段,不满足题意。同理R1R2
于是可以知道每一个位置最多是一种颜色的起点,一种颜色的终点。
L1<L2(反之也是一样),若R1>R2,则第一段颜色覆盖第二段颜色,所以必有R1<R2
对任意两段颜色都成立,则对所有颜色都成立。
所以有L1<L2<...<Ln,则必有R1<R2<...<Rn,且L1R1,L2R2,...,LnRn
由此可知,某个起点Li所对应的Ri与其位置无关,仅与已经确定的Ri的个数有关。
故考虑以下动态规划状态
dp[k][i][j]代表在已经确定前k1个格子中有i个起点和j个终点,为第k个格子确定四种状态之一:起点,终点,既是起点又是终点,不是起点也不是终点。
时间复杂度为O(n2m)

对于nm100000,考虑到如果n>m,则无解,故nm
由此推出n2nm105,则n<333,则n2m3.33107,可以在时限内运行完。因为一个格子的状态只与上一个格子的状态有关,可以用滚动数组优化内存空间。
dp是个好东西啊……
上代码

#include<cstdio>#define MOD 1000000007int dp[2][333][333];int n,m;int i,j,k;int main(){    scanf("%d %d",&n,&m);    if(n>m)//特判    {        printf("0");        return 0;    }    dp[0][0][0]=1;//初始    for(k=1;k<=m;k++)    {        for(i=0;i<=n;i++)            for(j=0;j<=i;j++) //终点数应小于等于起点数            {   //运用与运算压缩空间 k&1的结果为k%2                dp[k&1][i][j]=dp[k-1&1][i][j];                //这一格既不是起点也不是终点                if(i) dp[k&1][i][j]=(dp[k-1&1][i-1][j]+dp[k&1][i][j])%MOD;                //以这一格为起点                if(j) dp[k&1][i][j]=(dp[k-1&1][i][j-1]+dp[k&1][i][j])%MOD;                //以这一格为终点                if(i&&j) dp[k&1][i][j]=(dp[k-1&1][i-1][j-1]+dp[k&1][i][j])%MOD;                //既以这一格为起点,又以这一格为终点            }    }    printf("%d",dp[m&1][n][n]%MOD);    return 0;}
0 0
原创粉丝点击