洛谷P5279 [ZJOI2019]麻将(乱搞+概率期望)
题面
题解
看着题解里一堆巨巨熟练地用着专业用语本萌新表示啥都看不懂啊……顺便\(orz\)余奶奶
我们先考虑给你一堆牌,如何判断能否胡牌
我们按花色大小排序,设\(dp_{0/1,i,j,k}\)表示是否有对子,考虑了前\(i\)种花色的牌,选了\(j\)个以\(i-1\)为开头的顺子(三个连续牌),\(k\)个以\(i\)为开头的顺子,此时能选的最大面子数。转移的话枚举以\(i+1\)为开头的顺子的个数,剩下的组成刻子(三个相同牌)就好了(加一个数字记为\(Trans\))
那么胡牌的条件有两个,\(\exists i,j,dp_{1,n,j,k}\geq 4\),或者记\(cnt\)为牌数\(\geq 2\)的花色数,\(cnt\geq 7\)
这个东西和\(i\)这一维关系不是很大,我们可以把它当成一个\(3\times 3\)的矩阵来转移。我们可以用一个结构体\(node\)来表示这个矩阵,并且为了维护\(dp_0\)和\(dp_1\)我们需要开两个矩阵,并且记录\(cnt\),把这些所有都放到一个\(Mahjong\)结构体里。据说可行的\(Mahjong\)的状态只有\(3956\)个
然后期望可以转化为\(ans=\sum\limits_{i=13}^{4n}p(i)\),其中\(p(i)\)表示摸了\(i\)张牌还不能胡的概率,所以转化为算摸了\(i\)张牌还不能胡的排列数
设\(f_{i,j,k}\)表示我们考虑了前\(i\)种花色的牌,当前\(Mahjong\)的状态为\(j\),已经摸了\(k\)张牌的排列数是多少
转移的时候,我们枚举摸了花色\(i+1\)的张数\(z\),那么就可以转移到\(f_{i+1,Trans(j,z),k+z}\),乘上的系数是\((4 - org_{i + 1})^{\underline{z - org{i + 1}}} \binom{k + z - sum_{i + 1}}{z - org_{i + 1}}\) 。 \(org_i\) 表示原有的 \(13\) 张牌中花色为 \(i\) 的有几张, \(sum\) 则是 \(org\) 的前缀和,这个式子的意思就是我们需要在没被选过的 \(4 - org_{i + 1}\) 张牌中选 \(z - org_{i + 1}\) 张的排列,并且插入到之前的排列中,但前 \(13\) 张牌的顺序是固定的。
最后\(p_i\)就等于摸了\(i\)张牌不赢的排列数减去摸\(i\)张牌的排列数
//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
const int N=105,M=4005,P=998244353;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
int C[M][5],fac[5];
void init(){
fp(i,0,M-1){
C[i][0]=1;
fp(j,1,min(4,i))C[i][j]=add(C[i-1][j],C[i-1][j-1]);
}
fac[0]=1,fac[1]=1,fac[2]=2,fac[3]=6,fac[4]=24;
}
struct node{
int a[3][3];
node(){memset(a,-1,sizeof(a));}
inline void init(){memset(a,-1,sizeof(a));}
inline int* operator [](const int &x){return a[x];}
bool operator <(node b)const{
fp(i,0,2)fp(j,0,2)if(a[i][j]!=b[i][j])return a[i][j]<b[i][j];
return 0;
}
bool operator ==(node b)const{
fp(i,0,2)fp(j,0,2)if(a[i][j]!=b[i][j])return false;
return true;
}
friend node Max(node a,node b){
fp(i,0,2)fp(j,0,2)cmax(a[i][j],b[i][j]);
return a;
}
friend node Trans(node a,int b){
node res;
fp(i,0,2)fp(j,0,2)if(~a[i][j])
fp(k,0,min(2,b-i-j))
cmax(res[j][k],min(a[i][j]+i+(b-i-j-k)/3,4));
return res;
}
};
struct Mahjong{
node p[2];int cnt;
Mahjong(){p[0].init(),p[1].init(),p[0][0][0]=cnt=0;}
inline bool operator <(const Mahjong &b)const{
return cnt==b.cnt?p[0]==b.p[0]?p[1]<b.p[1]:p[0]<b.p[0]:cnt<b.cnt;
}
friend Mahjong Trans(Mahjong a,int b){
a.cnt=min(a.cnt+(b>=2),7);
a.p[1]=Trans(a.p[1],b);
if(b>=2)a.p[1]=Max(a.p[1],Trans(a.p[0],b-2));
a.p[0]=Trans(a.p[0],b);
return a;
}
bool right(){
if(cnt==7)return true;
fp(i,0,2)fp(j,0,2)if(p[1][i][j]==4)return true;
return false;
}
}mahjong[M];map<Mahjong,int>mp;
bool win[M];int n,tot,s[N],f[N][M][N<<2],trans[M][5];
void dfs(Mahjong now){
if(mp.count(now))return;
mahjong[++tot]=now,mp[now]=tot,win[tot]=now.right();
fp(i,0,4)dfs(Trans(now,i));
}
int main(){
// freopen("testdata.in","r",stdin);
init(),dfs(Mahjong());
fp(i,1,tot)fp(j,0,4)trans[i][j]=mp[Trans(mahjong[i],j)];
scanf("%d",&n);
for(R int i=1,x;i<=13;++i)scanf("%d%*d",&x),++s[x];
f[0][1][0]=1;
for(R int i=0,sum=0;i<n;++i){
sum+=s[i+1];
fp(j,1,tot)fp(l,s[i+1],4){
int *nf=f[i+1][trans[j][l]],*now=f[i][j];
int tmp=mul(C[4-s[i+1]][l-s[i+1]],fac[l-s[i+1]]);
fp(k,0,(n<<2)-l)if(now[k])
upd(nf[k+l],mul(now[k],mul(C[k+l-sum][l-s[i+1]],tmp)));
}
}
int ans=0;
for(R int i=13,res=1,up;i<=(n<<2);++i){
up=0;
fp(j,1,tot)if(!win[j])upd(up,f[n][j][i]);
upd(ans,mul(up,ksm(res,P-2))),res=mul(res,(n<<2)-i);
}
printf("%d\n",ans);
return 0;
}
洛谷P5279 [ZJOI2019]麻将(乱搞+概率期望)的更多相关文章
- 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)
洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\).我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...
- 洛谷P5279 [ZJOI2019]麻将
https://www.luogu.org/problemnew/show/P5279 以下为个人笔记,建议别看: 首先考虑如何判一个牌型是否含有胡的子集.先将牌型表示为一个数组num,其中num[i ...
- 洛谷P3959 宝藏(模拟退火乱搞)
题意 题目链接 题面好长啊...自己看吧.. Sol 自己想了一个退火的思路,没想到第一次交85,多退了几次就A了哈哈哈 首先把没用的边去掉,然后剩下的边从小到大排序 这样我们就得到了一个选边的序列, ...
- 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)
洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...
- 洛谷 P2059 [JLOI2013]卡牌游戏(概率dp)
题面 洛谷 题解 \(f[i][j]\)表示有i个人参与游戏,从庄家(即1)数j个人获胜的概率是多少 \(f[1][1] = 1\) 这样就可以不用讨论淘汰了哪些人和顺序 枚举选庄家选那张牌, 枚举下 ...
- 洛谷 P4548 - [CTSC2006]歌唱王国(概率生成函数)
洛谷题面传送门 PGF 入门好题. 首先介绍一下 PGF 的基本概念.对于随机变量 \(X\),满足 \(X\) 的取值总是非负整数,我们即 \(P(v)\) 表示 \(X=v\) 的概率,那么我们定 ...
- 洛谷P3211 [HNOI2011]XOR和路径(期望dp+高斯消元)
传送门 高斯消元还是一如既往的难打……板子都背不来……Kelin大佬太强啦 不知道大佬们是怎么发现可以按位考虑贡献,求出每一位是$1$的概率 然后设$f[u]$表示$u->n$的路径上这一位为$ ...
- 【洛谷3239_BZOJ4008】[HNOI2015] 亚瑟王(期望 DP)
题目: 洛谷 3239 分析: 卡牌造成的伤害是互相独立的,所以 \(ans=\sum f_i\cdot d_i\) ,其中 \(f_i\) 表示第 \(i\) 张牌 在整局游戏中 发动技能的概率.那 ...
- 【洛谷1654/BZOJ4318】OSU!(期望DP)
题目: 洛谷1654 分析: 本人数学菜得要命,这题看了一整天才看明白-- 先说说什么是"期望".不太严谨地说,若离散型随机变量(可以看作"事件")\(X\)取 ...
随机推荐
- 实现HBase增量入库(HBase删除自定义时间戳行数据)
目录 1. 背景描述 2. 问题描述 3. 解决方案 1. 背景描述 目前在做音乐推荐项目,前期做排序模型优化,任务是使用模型对用户的历史音乐进行排序,有6800多万个用户,约40G的用户数据,使用H ...
- Linux学习---linux的svn的配置与安装
1.检查是否已安装 rpm -qa subversion 如果要卸载旧版本: yum remove subversion 2.安装 yum install subversion 3.检查是否安装成 ...
- leetcode 20 Valid Parentheses 有效的括号
描述: 给定一些列括号,判断其有效性,即左括号有对应的有括号,括号种类只为小,中,大括号. 解决: 用栈. bool isValid(string s) { stack<char> st; ...
- WdatePicker.js的使用方法 帮助文档 使用说明(时间控件)
WdatePicker.js的使用方法 帮助文档 使用说明(时间控件) 4. 日期范围限制 静态限制 注意:日期格式必须与 realDateFmt 和 realTimeFmt 一致 你可以给通过配 ...
- 深入剖析java的try…catch…finally语句
一.前言 前些天参加面试的时候有一道题: public class test { public static void main(String[] args){ try { return; } fin ...
- Oracle ADF 创建序列
双击VO,打开Attribute 标签页在弹出的窗口中选择Default Value Type 为“Expression”, value 的值为:(new oracle.jbo.server.Sequ ...
- java 主类的main方法调用其他方法
方法1:A a=new test().new A(); 内部类对象通过外部类的实例对象调用其内部类构造方法产生,如下: public class test{ class A{ void fA(){ S ...
- oracle 建立表空间和用户
.建立表空间, create tablespace "NETHRA" DATAFILE 'D:\DataBase\Oracle\iClass\iclass\iclass.DBF' ...
- TOGAF架构培训材料学习总结
作于一个架构师尤其是企业架构师来说,丰富的理论知识可以帮助他在架构规划及管理过程中站在更高的角度去看待问题,历史发展原因有很多已成体系的架构理论,TOGAF是近年来比较接地气的,受到了政府和银 ...
- Spring boot——logback.xml 配置详解(三)<appender>
阅读目录 1 appender 2 encoder 文章转载自:http://aub.iteye.com/blog/1101260,在此对作者的辛苦表示感谢! 回到顶部 1 appender < ...