[ZJOI2019]麻将(DP+有限状态自动机)
首先只需要考虑每种牌出现的张数即可,然后判断一副牌是否能胡,可以DP一下,令f[i][j][k][0/1]表示到了第i位,用j次i-1,i,i+1和k次i,i+1,i+2,是否出现对子然后最大的面子数量,j,k∈[0,2],转移也很容易。这样暴力枚举可以获得50pts的“好”成绩。
然后可以丢掉第一维,只考虑18个状态最大可能对子数,强制f值<=4,最大对子数<=7,发现状态不到5000种。
然后把所有状态预处理,丢掉重复的状态,把有用状态建在自动机上。所以仅需从头到尾插入一种状态即可知道是否胡牌。
然后可以DP了,f[i][j][k]表示DP到第i种牌,状态在自动机j位置,抽了k张没胡的方案,直接转移即可。
#include<bits/stdc++.h>
using namespace std;
const int N=,mod=;
int n,tot,ans,c[][],fac[N],inv[N],has[N],f[][N][],ch[N][];
struct node{
int f[][][],cnt;
node(){memset(f,-,sizeof f),f[][][]=cnt=;}
bool operator<(const node&x)const
{
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
if(f[i][j][k]!=x.f[i][j][k])return f[i][j][k]<x.f[i][j][k];
return cnt<x.cnt;
}
}st[N];
void add(int&a,long long b){a=(a+b)%mod;}
map<node,int>S;
node trans(node u,int x)
{
node ret;
ret.cnt=min(u.cnt+(x>=),);
for(int a=;a<;a++)
for(int b=;a+b<;b++)
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
if(i+j+k+b*<=x&&u.f[a][i][j]!=-)
ret.f[a+b][j][k]=max(ret.f[a+b][j][k],min(u.f[a][i][j]+i+(x-i-j-k-b*)/,));
return ret;
}
int dfs(node u)
{
if(S.count(u))return S[u];
if(u.cnt==)return ;
for(int i=;i<;i++)for(int j=;j<;j++)if(u.f[][i][j]==)return ;
st[++tot]=u,S[u]=tot;
int pos=tot;
for(int i=;i<=;i++)ch[pos][i]=dfs(trans(u,i));
return pos;
}
int main()
{
scanf("%d",&n);
for(int i=,x;i<=;i++)scanf("%d%*d",&x),has[x]++;
for(int i=;i<=;i++)
{
c[i][]=;
for(int j=;j<=i;j++)c[i][j]=c[i-][j-]+c[i-][j];
}
fac[]=inv[]=inv[]=;for(int i=;i<=*n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=;i<=*n;i++)fac[i]=1ll*fac[i-]*i%mod,inv[i]=1ll*inv[i-]*inv[i]%mod;
dfs(node());
f[][][]=;
for(int i=;i<=n;i++)
{
memset(f[i&],,sizeof f[i&]);
for(int j=;j<=tot;j++)
for(int k=has[i];k<=;k++)
if(ch[j][k])
for(int t=;t<=(i-)*;t++)
add(f[i&][ch[j][k]][k+t],1ll*f[i-&][j][t]*c[-has[i]][k-has[i]]);
}
for(int i=,sum;i<=n*-;i++)
{
sum=;
for(int j=;j<=tot;j++)add(sum,f[n&][j][i+]);
add(ans,1ll*sum*fac[i]%mod*fac[*n--i]);
}
ans=(1ll*ans*inv[*n-]+)%mod;
printf("%d",ans);
}
[ZJOI2019]麻将(DP+有限状态自动机)的更多相关文章
- [ZJOI2019]麻将(动态规划,自动机)
[ZJOI2019]麻将(动态规划,自动机) 题面 洛谷 题解 先做一点小铺垫,对于一堆牌而言,我们只需要知道这\(n\)张牌分别出现的次数就行了,即我们只需要知道一个长度为\(n\)的串就可以了. ...
- 【Codeforces 506E】Mr.Kitayuta’s Gift&&【BZOJ 4214】黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化
神题……胡乱讲述一下思维过程……首先,读懂题.然后,转化问题为构造一个长度为|T|+n的字符串,使其内含有T这个子序列.之后,想到一个简单的dp.由于是回文串,我们就增量构造半个回文串,设f(i,j, ...
- [ZJOI2019]麻将
这是一道麻将自动机的模板题(雾 其实这是一道dp套dp借助自动机实现的麻将好题! 首先把期望转化一下,拆成sigema p(x>i) 现在要计算i张牌不胡的概率,也就等价于计算i张牌不胡的方案数 ...
- 用C语言实现有限状态自动机FSM
摘要:状态机模式是一种行为模式,在<设计模式>这本书中对其有详细的描述,通过多态实现不同状态的调转行为的确是一种很好的方法,只可惜在嵌入式环境下,有时只能写纯C代码,并且还需要考虑代码的重 ...
- 非确定有限状态自动机的构建(二)——将CharVal转换为NFA
保留版权,转载注明出处:潘军彪的个人博客(http://blog.csdn.net/panjunbiao/article/details/9378933) 将上下文无关文法读入内存之后,可以将它转换成 ...
- 非确定有限状态自动机的构建(一)——NFA的定义和实现
保留版权,转载需注明出处(http://blog.csdn.net/panjunbiao). 非确定有限状态自动机(Nondeterministic Finite Automata,NFA)由以下元素 ...
- DFA确定有限状态自动机
DFA 在计算理论中,确定有限状态自动机或确定有限自动机(英语:deterministic finite automaton, DFA)是一个能实现状态转移的自动机.对于一个给定的属于该自动机的状态和 ...
- K:有限状态自动机
有限状态自动机是一种特殊的状态机.它表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型.有限状态自动机分为两种,一种是 确定有限状态自动机(DFA) ,一种是 非确定有限状态自动机(NF ...
- 咕咕(数位dp+AC自动机)
咕咕(数位dp+AC自动机) 若一个字符串的字符集合是0~m-1,那么称它为m进制字符串.给出n个m进制字符串\(s_i\),每个字符串的权值为\(v_i\).对于另一个m进制字符串\(S\),设\( ...
随机推荐
- Dubbo+Zookeeper 入门Demo
1.Zookeeper安装及启动 可参考这篇文章https://www.cnblogs.com/geekdc/p/5948326.html 从下载到启动都描述的很详细,按照文章一步一步走即可. 2.D ...
- Mount error(5):Input/output error on mount
https://superuser.com/questions/850301/mount-error5input-output-error-on-mount When setting up a sha ...
- 从架构师视角看是否该用Kotlin做服务端开发?
前言 自从Oracle收购Sun之后,对Java收费或加强控制的尝试从未间断,谷歌与Oracle围绕Java API的官司也跌宕起伏.虽然Oracle只是针对Oracle JDK8的升级收费,并释放了 ...
- swtich多个case使用同一操作
switch (expression) { case 'status01': case 'status02': case 'status03': alert('resultOne'); break; ...
- java 的二分算法
二分算法 就是在 一组 有序 数组中 通过中间值(数组中间的那个数字)的方法 找到 某个数的下标,如果大于中间值 ,则在中间值与最大值之间 的中间值再比较. public class two { // ...
- JavaScript学习总结(一)
概述 前端三剑客,html.css.js. 这三种语言基本是前端开发必备的东西,那么你知道这三种语言分别负责的功能是什么吗? html:负责了一个页面的结构 css:负责页面的样式 JavaScrip ...
- 系统学习python第五天学习笔记
1.列表补充 extend() li = ["alex", "WuSir", "ritian", "barry", &q ...
- Django框架(十一):模板介绍、模板语言、模板继承、HTML转义
1. 模板介绍 1.1 模板的功能 产生html,控制页面上展示的内容.模板文件不仅仅是一个html文件. 模板文件包含两部分内容: 静态内容:css.js.html. 动态内容:用于动态去产生一些页 ...
- bugs开发异常解决方法
1. 前提 第一层:遇到异常首先必须告诉自己,冷静,不要慌.(一看到Bug就心慌,那么就不能释放必杀技) 2. 入门级 第二层:遇到Bug,第一潜意识看输出异常的信息的(控制台输出 ...
- 在线公开课 | 5G时代的视频云服务关键技术与实践
5G时代来临在即,视频技术将会如何发展呢?基于视频云服务的技术开发又有怎样的变化呢?为此,京东云视频云产品研发部高级总监魏伟为大家做出了详细解读. 魏伟拥有10多年视频行业研发经验,先后从事于AVS标 ...