传送门

打麻将+1(雾

有顺子这种东西...注意到以某个位置为开头的顺子数量最多为2,那么有个想法就是枚举以每个位置为开头的顺子个数,然后每个位置的刻子的取法个数为\(\lceil\frac{\text{剩下的牌数}}{3}\rceil\),乘起来,然后每种情况的和就是答案

所以设\(f_{i,j,k}\)表示放到\(i\)牌,有\(j\)个\(i-1,i,i+1\)以及\(k\)个\(i,i+1,i+2\)的方案.转移枚举下一位放多少顺子(注意最后两个位置只能放0个),然后乘上刻子的取法个数进行转移,因为有些位置必须要用一些牌,所以方案应该改为(下面\(x\)为这一位用顺子消耗的牌数,\(a\)为这一位至少要用的牌数)$$\begin{cases}\lceil\frac{c-x}{3}\rceil&,x\ge a\\lceil\frac{c-(x+3 \lceil\frac{a-x}{3}\rceil)}{3}\rceil&,x< a\end{cases}$$

然后注意到\(n\)很大,并且很多位置都是随便用任意张牌,然后有限制的地方很少,所以有限制的地方以及最后两位暴力转移,剩下的地方矩乘转移

// luogu-judger-enable-o2
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double using namespace std;
const int N=1000+10,mod=998244353;
LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
struct matrix
{
int a[9][9];
matrix(){memset(a,0,sizeof(a));}
matrix operator * (const matrix &bb) const
{
matrix an;
for(int i=0;i<9;++i)
for(int j=0;j<9;++j)
{
LL nw=0;
for(int k=0;k<9;++k) nw+=1ll*a[i][k]*bb.a[k][j];
an.a[i][j]=nw%mod;
}
return an;
}
matrix operator ^ (const LL &bb) const
{
matrix an,a=*this;
for(int i=0;i<9;++i) an.a[i][i]=1;
LL b=bb;
while(b)
{
if(b&1) an=an*a;
a=a*a,b>>=1;
}
return an;
}
}aa,bb;
LL n,a[N][2];
int c,m,id[3][3],tmp[9]; int main()
{
n=rd(),c=rd(),m=rd();
for(int i=1;i<=m;++i) a[i][0]=rd(),a[i][1]=rd();
a[m+1][0]=n+1;
int ii=0;
aa.a[0][0]=1;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
id[i][j]=i*3+j;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
for(int k=0;k<3;++k)
bb.a[id[i][j]][id[j][k]]=max((c-i-j-k+3)/3,0);
for(;ii<=m;)
{
LL l=max(min(n-2,a[ii+1][0]-1)-(a[ii][0]+1)+1,0ll);
aa=aa*(bb^l);
++ii;
if(a[ii][0]>n-2) break;
memset(tmp,0,sizeof(tmp));
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
for(int k=0;k<3;++k)
{
int num=i+j+k<=a[ii][1]?i+j+k+(a[ii][1]-i-j-k+2)/3*3:i+j+k;
tmp[id[j][k]]=(tmp[id[j][k]]+1ll*aa.a[0][id[i][j]]*max((c-num+3)/3,0)%mod)%mod;
}
memcpy(aa.a[0],tmp,sizeof(tmp));
}
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
for(int k=1;k<3;++k)
bb.a[id[i][j]][id[j][k]]=0;
for(LL h=n-1;h<=n;++h,++ii)
{
while(h<=n&&h<a[ii][0]) aa=aa*bb,++h;
if(h>n) break;
memset(tmp,0,sizeof(tmp));
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
{
int num=i+j<=a[ii][1]?i+j+(a[ii][1]-i-j+2)/3*3:i+j;
tmp[id[j][0]]=(tmp[id[j][0]]+1ll*aa.a[0][id[i][j]]*max((c-num+3)/3,0)%mod)%mod;
}
memcpy(aa.a[0],tmp,sizeof(tmp));
}
printf("%d\n",aa.a[0][0]);
return 0;
}

luogu P5371 [SNOI2019]纸牌的更多相关文章

  1. Luogu 1031 - 均分纸牌 - [有意思的思维题]

    题目链接:https://www.luogu.org/problemnew/show/P1031 题目描述有 $N$ 堆纸牌,编号分别为 $1,2,…,N$.每堆上有若干张,但纸牌总数必为 $N$ 的 ...

  2. luogu P1031 均分纸牌

    题目很简单,但是可以学一学贪心策略 把纸牌均匀分布,从左往右推掉不用的纸牌 #include <iostream> using namespace std; int main() { in ...

  3. [SNOI2019]纸牌

    传送门 Description 有一副纸牌.牌一共有\(n\)种,分别标有 \(1,2,...,n\),每种有\(C\)张.故这副牌共有\(nC\)张. 三张连号的牌(\(i,i+1,i+2\))或三 ...

  4. Luogu P5330 [SNOI2019]数论

    题目 如果\(P>Q\)的话我们先交换一下\(P,Q\). 我们先枚举所有满足第一个条件的数,对于\(x\equiv a_i(mod\ P)\),设\(x=a_i+kP(k\in[0,\lflo ...

  5. luogu P5331 [SNOI2019]通信

    传送门 有匹配次数限制,求最小代价,这显然是个费用流的模型.每个点暴力和前面的点连匹配边,边数是\(n^2\)的. 然后发现可以转化成一个set,每次加入一个点,然后入点对set里面的出点连边.这个s ...

  6. luogu P5329 [SNOI2019]字符串

    传送门 显然要写一个排序,那只要考虑cmp函数怎么写就行了.第\(i\)个字符串和第 \(j\)个,首先前\(min(i,j)-1\)个字符是相同的,然后就是要比较后缀\(min(i,j)\)和\(m ...

  7. 【LOJ】#3098. 「SNOI2019」纸牌

    LOJ#3098. 「SNOI2019」纸牌 显然选三个以上的连续牌可以把他们拆分成三个三张相等的 于是可以压\((j,k)\)为有\(j\)个连续两个的,有\(k\)个连续一个的 如果当前有\(i\ ...

  8. Luogu P4016 负载平衡问题

    传说中的网络流24题之一,我刷的第二题菜. 据说这种东西做完了就可以有质的飞越?不过看着这些Luogu评级就有点蒙蔽. 首先我们看一下题目发现这不是均分纸牌的加强板吗,但是那个环的操作极大地限制了我的 ...

  9. 洛谷——P1031 均分纸牌

    https://www.luogu.org/problem/show?pid=1031#sub 题目描述 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以 ...

随机推荐

  1. Spring boot之添加JSP支持

    大纲 (1) 创建Maven web project: (2) 在pom.xml文件添加依赖 (3) 配置application.properties支持jsp (4) 编写测试Controller ...

  2. Eclipse的JSON文件报错解决

    有时候我们后端老哥不想写HTML,偷懒去下载个前端页面,结果里面的JSON文件老报错 虽然可以正常运行,但红X看起来就是不爽,怎么解决呢 这是因为Eclipse认为JSON文件不需要注释,所以报的编译 ...

  3. linux pwd指令的C实现

    linux pwd指令的C实现 pwd指令的功能介绍 linux pwd命令用于显示工作目录 执行pwd命令可立刻得知当前所在工作目录的绝对路径名称. 示例: 查询系统手册 如图所示,getcwd的描 ...

  4. 【转】Java操作CSV文件导入导出

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  5. Arch linux(UEFI+GPT)安装及后续优化教程

    Arch Linux安装过程中需要从远程存储库获取软件包,电脑需要有效的互联网连接. 1.联网 查看是否有网 ping www.baidu.com 同步时间 timedatectl set-ntp t ...

  6. MyExcel 2.2.0 版本发布,支持公式导出

    MyExcel,是一个集导入.导出.加密Excel等多项功能的java工具包. 相关链接 MyExcel 的详细介绍:点击查看 MyExcel 的下载地址:点击下载

  7. Centos6 源码安装mysql5.6

    这里介绍如何使用centos6.*来安装mysql5.6版本. 先做一下准备工作 确定好用于运行mysql的用户,安全起见,建议拒绝次用户登录,仅用于运行程序. useradd mysql -s/sb ...

  8. 一、基础篇--1.2Java集合-Arraylist 与 LinkedList 区别

     Arraylist 与 LinkedList 区别  结构上的区别 ArrayList底层实现基于动态数组,LinkedList底层实现基于双向链表.  性能上区别 ArrayList查询快,增删慢 ...

  9. Jmeter(十一)测试监听

    性能测试监控的主要任务是获取运行状态收集测试结果, 再对测试结果进行分析. 测试结果有事务响应时间,吞吐量及服务器硬件性能 , 数据库性能状态等等. Jmeter对长时间执行测试计划使用的监听器主要是 ...

  10. java:JavaScript3(innerHTML,post和get,单选框,多选框,下拉列表值得获取,JS中的数组,JS中的正则)

    1.innerHTML用户登录验证: <!DOCTYPE> <html> <head> <meta charset="UTF-8"> ...