Codeforces 1392H - ZS Shuffles Cards(DP+打表找规律)
真·两天前刚做过这场的 I 题,今天模拟赛就考了这场的 H 题,我怕不是预言带师
提供一种奇怪的做法,来自于同机房神仙们,该做法不需要 Min-Max 容斥,也不用爆推组合数,只需要比较强的眼力的初中数学求解二元一次方程组知识。
期望题没往 Min-Max 容斥的方向去想,不愧是我(大雾
首先我们先考虑一些复杂度比较高的多项式复杂度做法。注意到对于任何一个局面而言,我们并不用关心 \(S\) 里究竟具体有哪些数,也不用关心牌堆中具体有哪些数字牌,我们只用关心有多少个数在 \(S\) 中,以及牌堆中还剩多少张牌。因此我们可以设 \(dp_{i,j}\) 表示牌堆中还剩 \(i\) 张牌,\(S\) 中已经有 \(j\) 个数,期望还需多少步,那么:
对于 \(j\ne n\),下一次摸出一张牌,有三种可能:
- 摸出一张数字牌,且不在 \(S\) 中,概率 \(\dfrac{n-j}{i+m}\),并且会到达状态 \(dp_{i-1,j+1}\),因此 \(dp_{i,j}\leftarrow dp_{i-1,j+1}·\dfrac{n-j}{i+m}\)
- 摸出一张数字牌,且在 \(S\) 中,概率 \(\dfrac{i+j-n}{i+m}\),并且会到达状态 \(dp_{i-1,j}\),因此 \(dp_{i,j}\leftarrow dp_{i-1,j}·\dfrac{i+j-n}{i+m}\)
- 摸出一张鬼牌,概率 \(\dfrac{m}{i+m}\),并且会到达状态 \(dp_{n,j}\),因此 \(dp_{i,j}\leftarrow dp_{n,j}·\dfrac{m}{i+m}\)。
别忘了加上最后的 \(1\),因此对于 \(j\ne 0\) 的情况我们有转移方程 \(dp_{i,j}=dp_{i-1,j+1}·\dfrac{n-j}{i+m}+dp_{i-1,j}·\dfrac{i+j-n}{i+m}+dp_{n,j}·\dfrac{m}{i+m}+1\)。
对于 \(j=n\) 的情况就比较 trivial 了,如果摸出一张数字牌那么会到达 \(dp_{i-1,j}\),否则直接结束,因此 \(dp_{i,n}=dp_{i-1,n}·\dfrac{i}{i+m}+1\)
最终答案即为 \(dp_{n,0}\)
由于 DP 转移存在后效性,因此直接转移不可取,考虑高斯消元,直接高斯消元是六方的,不过注意到对于一个 \(dp_{i,j}\) 而言,如果我们倒着枚举 \(j\),那么我们就只用对 \(j\) 相同的这一行的值进行高斯消元,复杂度 \(n^4\)。还可以进一步优化,就是注意到在我们倒序枚举的过程中 \(dp_{i-1,j+1}·\dfrac{n-j}{i+m}\) 是常数不用管它,如果我们不考虑这个 \(dp_{n,j}\) 那转移关系不成环就不存在后效性,而加上这个 \(dp_{n,j}\),由于导致这个后效性的只有 \(dp_{n,j}\),我们就可以考虑将所有 \(dp_{i,j}\) 都表示成 \(sdp_{n,j}+t\) 的形式,这样顺着一遍推过去,最后可以得到 \(dp_{n,j}=sdp_{n,j}+t\),解出 \(dp_{n,j}\) 后再推回去即可,这个套路可以在这道题中找到,时间复杂度 \(n^2\),反正还是过不去(
附:\(n^2\) 的代码:
const int MAXN=1000;
const int MOD=998244353;
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
int n,m,dp[MAXN+5][MAXN+5];
int main(){
// freopen("toad.in","r",stdin);
// freopen("toad.out","w",stdout);
scanf("%d%d",&n,&m);
dp[0][n]=1;
for(int i=1;i<=n;i++) dp[i][n]=(1ll*i*qpow(i+m,MOD-2)%MOD*dp[i-1][n]+1)%MOD;
for(int j=n-1;~j;j--){
int cs=0,ct=0;
for(int i=n-j;i<=n;i++){
int coef1=1ll*m*qpow(i+m,MOD-2)%MOD;
int coef2=1ll*(i+j-n+MOD)*qpow(i+m,MOD-2)%MOD;
int coef3=1ll*(n-j)*qpow(i+m,MOD-2)%MOD;
cs=1ll*cs*coef2%MOD;ct=1ll*(ct+1)*coef2%MOD;
ct=(ct+1ll*(dp[i-1][j+1]+1)*coef3)%MOD;
cs=(cs+coef1)%MOD;ct=(ct+coef1)%MOD;
} dp[n][j]=1ll*ct*qpow((1-cs+MOD)%MOD,MOD-2)%MOD;//dp[n][j]=cs*dp[n][j]+ct
for(int i=n-j;i<n;i++){
int coef1=1ll*m*qpow(i+m,MOD-2)%MOD;
int coef2=1ll*(i+j-n+MOD)*qpow(i+m,MOD-2)%MOD;
int coef3=1ll*(n-j)*qpow(i+m,MOD-2)%MOD;
dp[i][j]=(1ll*(dp[i-1][j]+1)*coef2+1ll*(dp[i-1][j+1]+1)*coef3%MOD+1ll*(dp[n][j]+1)*coef1)%MOD;
// printf("%d %d %d\n",i,j,dp[i][j]);
} //printf("%d %d %d\n",n,j,dp[n][j]);
} printf("%d\n",dp[n][0]);
return 0;
}
接下来考虑进一步优化。这里就要一些观察了,打个表可以发现,对于 \(j\) 相同的 \(dp_{i,j}\) 而言随着 \(i\) 的增大 \(dp_{i,j}\) 成等差数列,换句话说所有 \(dp_{i,j}\) 都可以写成 \(k_ji+b_j\) 的形式。证明不会,大概可以归纳(?)(大概就发现 \(dp_{i,n}\) 是等差数列,而 \(dp_{i,j}\) 只从 \(dp_{i,j+1}\) 推来,这就天然地形成了归纳的模型,但具体怎么归纳我也没想出来)。这样对于每一个 \(j\),我们只用确定 \(dp_{n,j}\) 和 \(dp_{n-1,j}\),所有 \(dp_{i,j}\) 都确定了,方便起见这里假设 \(dp_{i,j}=y_j(n-i)+x_j\),这样我们可以列出这样两个方程组:
x_j=dp_{n-1,j+1}·\dfrac{n-j}{n+m}+(x_j+y_j)·\dfrac{j}{n+m}+x_j·\dfrac{m}{n+m}+1\\
x_j+y_j=dp_{n-2,j+1}·\dfrac{n-j}{n+m-1}+(x_j+2y_j)·\dfrac{j-1}{n+m-1}+x_j·\dfrac{m}{n+m-1}+1
\end{cases}
\]
把 \(x_j,y_j\) 解出来即可。
时间复杂度 \(n\log n\),好像做不到 \(\mathcal O(n)\)
const int MAXN=2e6;
const int MOD=998244353;
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
int n,m,x[MAXN+5],y[MAXN+5],f[MAXN+5];
int calc(int i,int j){return (x[j]+1ll*(n-i)*y[j]%MOD)%MOD;}
int main(){
scanf("%d%d",&n,&m);int ivn=qpow(n+m,MOD-2),ivn1=qpow(n-1+m,MOD-2);
f[0]=1;for(int i=1;i<=n;i++) f[i]=(1ll*i*qpow(i+m,MOD-2)%MOD*f[i-1]+1)%MOD;
x[n]=f[n];y[n]=(f[n-1]-f[n]+MOD)%MOD;
for(int j=n-1;j;j--){
int a1=1ll*(n-j)*ivn%MOD;
int b1=(MOD-1ll*j*ivn%MOD)%MOD;
int c1=1ll*(n-j)*ivn%MOD*calc(n-1,j+1)%MOD;
int a2=1ll*(n-j)*ivn1%MOD;
int b2=(1-1ll*(j-1+MOD)*2*ivn1%MOD+MOD)%MOD;
int c2=1ll*(n-j)*ivn1%MOD*calc(n-2,j+1)%MOD;
(c1+=1)%=MOD;(c2+=1)%=MOD;
y[j]=1ll*(1ll*c1*a2%MOD-1ll*c2*a1%MOD+MOD)*qpow((1ll*b1*a2%MOD-1ll*b2*a1%MOD+MOD)%MOD,MOD-2)%MOD;
x[j]=1ll*(c1-1ll*y[j]*b1%MOD+MOD)*qpow(a1,MOD-2)%MOD;
} printf("%d\n",1ll*(1ll*calc(n-1,1)*n%MOD*ivn%MOD+1ll*m*ivn%MOD)*qpow(n,MOD-2)%MOD*(n+m)%MOD+1);
return 0;
}
Codeforces 1392H - ZS Shuffles Cards(DP+打表找规律)的更多相关文章
- HDU 4588 Count The Carries 数位DP || 打表找规律
2013年南京邀请赛的铜牌题...做的非常是伤心.另外有两个不太好想到的地方.. ..a 能够等于零,另外a到b的累加和比較大.大约在2^70左右. 首先说一下解题思路. 首先统计出每一位的1的个数, ...
- Tetrahedron(Codeforces Round #113 (Div. 2) + 打表找规律 + dp计数)
题目链接: https://codeforces.com/contest/166/problem/E 题目: 题意: 给你一个三菱锥,初始时你在D点,然后你每次可以往相邻的顶点移动,问你第n步回到D点 ...
- Codeforces 193E - Fibonacci Number(打表找规律+乱搞)
Codeforces 题目传送门 & 洛谷题目传送门 蠢蠢的我竟然第一眼想套通项公式?然鹅显然 \(5\) 在 \(\bmod 10^{13}\) 意义下并没有二次剩余--我真是活回去了... ...
- codeforces#1090 D. New Year and the Permutation Concatenation(打表找规律)
题意:给出一个n,生成n的所有全排列,将他们按顺序前后拼接在一起组成一个新的序列,问有多少个长度为n的连续的子序列和为(n+1)*n/2 题解:由于只有一个输入,第一感觉就是打表找规律,虽然表打出来了 ...
- Codeforces Round #493 (Div. 2)D. Roman Digits 第一道打表找规律题目
D. Roman Digits time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- Codeforces Beta Round #24 D. Broken robot (打表找规律)
题目链接: 点击我打开链接 题目大意: 给你 \(n,j\),再给出 \(m[0]\) 的坐标和\(a[0]-a[n-1]\) 的坐标. 让你输出 \(m[j]\) 的坐标,其中 \(m[i]\) 和 ...
- 打表找规律C - Insertion Sort Gym - 101955C
题目链接:https://cn.vjudge.net/contest/273377#problem/C 给你 n,m,k. 这个题的意思是给你n个数,在对前m项的基础上排序的情况下,问你满足递增子序列 ...
- Nowcoder 练习赛 17 C 操作数 ( k次前缀和、矩阵快速幂打表找规律、组合数 )
题目链接 题意 : 给定长度为n的数组a,定义一次操作为: 1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007: 2. ...
- hdu 3032 Nim or not Nim? (SG函数博弈+打表找规律)
Nim or not Nim? Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Sub ...
随机推荐
- 【UE4】GamePlay架构
新标签打开或者下载看大图 更新: 增加 编程子系统 Subsystem 思维导图 Character pipeline
- python打印爱心
print('\n'.join([''.join([('AndyLove'[(x-y)%8]if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3 ...
- 6月8日 Scrum Meeting
日期:2021年6月8日 会议主要内容概述: 确定6.9日下午两点到五点集中对接 初步确定主题配色和echarts默认图表颜色 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作 ...
- 使用jave2实现将wav格式的音频转换成mp3格式
最近需要用到语音合成功能,网上查阅了一番,发现可以使用腾讯云的语音合成API来完成这个功能,但是腾讯云的api返回的是wav格式的音频文件,这个格式的文件有些不通用,因此需要转换成mp3格式的文件. ...
- Stack2 攻防世界题目分析
---XCTF 4th-QCTF-2018 前言,怎么说呢,这题目还是把我折磨的可以的,我一开始是没有看到后面的直接狙击的,只能说呢. 我的不经意间的粗心,破坏了你许多的温柔 1.气的我直接检查保护: ...
- K8S_Kubernetes
Google创造, K8S,是基于容器的集群管理平台, K8S集群 应用场景 微服务 这个集群主要包括两个部分 一个Master节点(主节点) 一群Node节点(计算节点) Master节 ...
- ASP.NET WEBAPI 跨域请求 405错误
浏览器报错 本来没有报这个错,当我在ajax中添加了请求头信息时报错 405的报错大概就是后端程序没有允许此次请求,要解决这个问题,就是在后端程序中允许请求通过.具体操作就是修改web.config配 ...
- 关于linux的fork的一点学习总结
最近操作系统的实验要用到fork,于是去搜索了一下资料,很幸运地在博客中找到一篇深度好文: http://blog.csdn.net/jason314/article/details/5640969 ...
- DeWeb 电脑和手机动态适配
DeWeb 做多平台适配很方便! 多平台适配代码在OnMouseUp中. X,Y分别表示当前设备的Width/Height: Button : mbLeft : 屏幕纵向, mbRight:屏幕横向: ...
- JMeter学习笔记--关联
1.什么是关联? 本次请求需要的数据,需要上一步的请求返回给提供的过程. 2.JMeter关联中常用的两种方式 正则表达式提取器 正则表达式提取器用于对页面任何文本的提取,提取的内容是根据正则表达式在 ...