zoukankan      html  css  js  c++  java
  • ZOJ 3747 Attack On Titan

    原题链接

    题意简述:

    给定 N、M、K(N<=10^6),求有多少种给 N 个物品染色的方式,使得至少有一个子段满足染色为 G 的有连续 M 个,染色为 R 的至多连续 K 个。每个物品必须染色成 R、G、B 中的一种。

    题意分析:

    条件“至少一个子段满足有连续M个”不方便转移,可以转化为 至多有 N 个连续的的方案 减去 至多有 M-1 个连续的的方案。
    那么两问统一成一个问题:求染色为 X 的至多连续 K 个的方案数。
    接下来就考虑分情况讨论递推。假设当前为第 i 个物品,且之前的序列符合要求

    • 当 i < k 时。显然,无论怎么染色都没关系。
    • 当 i = k 时。显然,就是上一种情况减去唯一的一种不合法方案——全部为 X 的方案数。
    • 当 i > k 时。如果此时放上 X 刚好不满足条件,就说明 [i-K+1,i-1] 均为 X ,我们要减去这类方案。显然,这类方案的个数恰好就为 第 i-k 位的物品为其余两种颜色的方案数的总和。

    那么根据第三种情况,可以发现当在DP状态中设置“颜色”这一维度时有利于递推。
    于是设状态 dp[i][0~2] 表示第 i 个物品染色为 0~2 中的某一种时的合法方案总数。递推就根据之前的分类讨论来就行啦。

    代码分享:

    long long Solve(int u,int v){
    	f[0][0]=1;f[0][1]=f[0][2]=0;
    	for(int i=1;i<=n;++i){
    		long long sum=(f[i-1][0]+f[i-1][1]+f[i-1][2])%Mod;
    		f[i][2]=sum;
    		if(i<=u) f[i][0]=sum;
    		else if(i==u+1) f[i][0]=sum-1;
    		else if(i>u+1) f[i][0]=(sum-f[i-u-1][1]-f[i-u-1][2]+Mod+Mod)%Mod;
    		if(i<=v) f[i][1]=sum;
    		else if(i==v+1) f[i][1]=sum-1;
    		else if(i>v+1) f[i][1]=(sum-f[i-v-1][0]-f[i-v-1][2]+Mod+Mod)%Mod;
    	}
    	return (f[n][0]+f[n][1]+f[n][2])%Mod;
    }
    

    反思归纳:

    遇到计数题目时,先对条件逐一思考,遇到刁钻的条件可以考虑转化来求解。
    在转移时,通常进行分类讨论。可以先分类讨论,分析出在什么情况下自己需要那些信息来推出当前信息,并据此来设置状态转移方程。

  • 相关阅读:
    C#中使用SendMessage在进程间传递数据的实例
    解决C# WINFORM程序只允许运行一个实例的几种方法详解
    实现WinForm窗体的美化(借助第三方控件)
    sql2008拒绝了对对象 (数据库 ,架构'dbo')的SELECT权限
    在一个SQL Server表中一行的多个列找出最大值
    如何搭建MVC + EF 框架
    灵活运用 SQL SERVER FOR XML PATH
    CentOS7切换到root用户和退回普通用户
    Zuul Read Time out 错误
    neo4j---删除关系和节点
  • 原文地址:https://www.cnblogs.com/parauni-blog/p/13060680.html
Copyright © 2011-2022 走看看