传送门

Description

有一副纸牌。牌一共有\(n\)种,分别标有 \(1,2,...,n\),每种有\(C\)张。故这副牌共有\(nC\)张。

三张连号的牌(\(i,i+1,i+2\))或三张相同的牌 \((i,i,i)\) 可以组成一叠。如果一组牌可以分成若干(包括零)叠,就称其为一组王牌

你从牌堆中摸了一些初始牌。现在你想再挑出一些牌组成一组王牌,请问有多少种可能组成的王牌呢?答案对\(998244353\)取模。

两组牌相同当且仅当它们含有的每一种牌数量都相同。

Solution

发现这道题中的\(n\)很大,所以考虑矩阵乘法

发现\((i,i+1,i+2)\)这样的牌,对于相同的\(i\),最多只有两叠

所以考虑一个\(3*3\)的状态表示当前数\(i\)与\(i-1\)开始的顺子的数量\((0,1,2)\)

考虑如何转化到下一个数,发现需要枚举\(i+1\)开始的顺子数,将其乘上可行的\((i+1,i+1,i+1)\)的数量的个数

将原题的\(dp\)转化位矩阵乘法

对于已经有初始牌的数,我们考虑单独拿出来转移

可以先把转移矩阵的次幂算出来,减小常数

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define reg register
#define int ll
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int P=998244353,MX=1005;
ll n,C,X,A[MX],K[MX];
int Mul(int x,int y){return (1LL*x*y)%P;}
int Add(int x,int y){return (x+y)%P;}
struct Matrix
{
int a[9][9];
Matrix(){memset(a,0,sizeof a);}
void emp(){for(int i=0;i<9;++i)a[i][i]=1;}
Matrix operator *(Matrix b)
{
Matrix c;
register int i,j,k;
for(k=0;k<9;++k)for(i=0;i<9;++i)for(j=0;j<9;++j)
c.a[i][j]=Add(c.a[i][j],Mul(b.a[i][k],a[k][j]));
return c;
}
}tmp,opt[70],ans;
Matrix OPT(int m)
{
Matrix r;int x=0;r.emp();
for(;m;m>>=1,++x)if(m&1)r=r*opt[x];
return r;
}
signed main()
{
n=read();C=read();X=read();
register int i,j,k,l;
for(i=1;i<=X;++i) K[i]=read(),A[i]=read();
for(i=0;i<3;++i)for(j=0;j<3;++j)for(k=0;k<3;++k)
if(i+j+k<=C)opt[0].a[j*3+k][i*3+j]=1+(C-i-j-k)/3;
for(i=1;i<70;++i) opt[i]=opt[i-1]*opt[i-1];
ans.a[0][0]=1;
for(l=1;l<=X;++l)
{
ans=ans*OPT(K[l]-K[l-1]-1);
memset(tmp.a,0,sizeof tmp.a);
for(i=0;i<3;++i)for(j=0;j<3;++j)for(k=0;k<3;++k)
{
int least=i+j+k;
if(least<A[l]) least=A[l]+((least-A[l])%3+3)%3;
if(least<=C) tmp.a[j*3+k][i*3+j]=1+(C-least)/3;
}
ans=ans*tmp;
}
ans=ans*OPT(n-K[X]);
printf("%lld\n",ans.a[0][0]);
return 0;
}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

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

  1. luogu P5371 [SNOI2019]纸牌

    传送门 打麻将+1(雾 有顺子这种东西...注意到以某个位置为开头的顺子数量最多为2,那么有个想法就是枚举以每个位置为开头的顺子个数,然后每个位置的刻子的取法个数为\(\lceil\frac{\tex ...

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

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

  3. code vs 1098 均分纸牌(贪心)

    1098 均分纸牌 2002年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解   题目描述 Description 有 N 堆纸牌 ...

  4. C语言-纸牌计算24点小游戏

    C语言实现纸牌计算24点小游戏 利用系统时间设定随机种子生成4个随机数,并对4个数字之间的运算次序以及运算符号进行枚举,从而计算判断是否能得出24,以达到程序目的.程序主要功能已完成,目前还有部分细节 ...

  5. 一起来做webgame,《Javascript蜘蛛纸牌》

    不得不说,做游戏是会上瘾的,这次带来的是win系统上的经典游戏<蜘蛛纸牌>,不能完美,但求一玩 移牌 0 次 Javascript game_蜘蛛纸牌 正在努力加载... // " ...

  6. 洛谷 P1031 均分纸牌 Label:续命模拟QAQ

    题目描述 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以在任一堆上取若于张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 ...

  7. 斯坦福iOS7公开课1-3笔记及纸牌Demo

    1.MVC Model:模型 描述程序是什么,例如数据库操作之类的行文以及纸牌Demo里纸牌玩法都是写在Model这一层,通过Notification和KVO(后续文章会介绍)两种方式与Control ...

  8. [CareerCup] 8.1 Implement Blackjack 实现21点纸牌

    8.1 Design the data structures for a generic deck of cards. Explain how you would subclass the data ...

  9. 纸牌project

    用range[0,8)的列表表示牌,这些数字要出现两次.我们建议你通过连接两个range[0,8)的列表来创建这个list.利用Docs来安排列表串联操作 写一个draw handler啥样的draw ...

随机推荐

  1. 谈谈MySQL中的锁

    谈谈MySQL中的锁 锁的定义 ​ 在生活中锁的例子就非常多了,所以应该很容易理解锁的含义.在计算机领域,可以这样来概述,锁是计算机协调多个进行进程并发访问某一资源的机制. ​ 在数据库中,锁也是一个 ...

  2. 【开发工具】- Myeclipse10.7破解方法

    1.下载myeclipse 10,如果没有,可以使用链接:https://pan.baidu.com/s/1l9juqD4ALMuepVL6e5kgjA 密码:kpx6:当然时间久了可能链接失效,如有 ...

  3. C语言判断字符串是否是 hex string的代码

    把写内容过程中经常用到的一些内容段备份一下,如下内容内容是关于C语言判断字符串是否是 hex string的内容. { static unsigned int hex2bin[256]={0}; me ...

  4. S/4HANA Service Management和SAP Field Service Management的集成

    经常有朋友提出这样的问题:"SAP Business Suite里的CRM的Service模块已经通过Addon的方式迁移到了S/4HANA上,并且SAP之前又收购了一家专门做Service ...

  5. Flask整合WebLoader 用于大附件拆分上传再合并

    博客:https://blog.csdn.net/jinixin/article/details/77545140 github:https://github.com/jinixin/upload-d ...

  6. 【RAC】将单实例备份集恢复为rac数据库

    [RAC]将单实例备份集恢复为rac数据库 一.1  BLOG文档结构图 一.2  前言部分 一.2.1  导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识, ...

  7. day 02 作业 预科

    目录 作业 作业 ==1.什么是编程== 通过使用编程语言做一些事情,表达一些自己的想法. ==2.简述计算机五大组成.== 计算机由cpu ,运算器 ,控制器,存储器(外存,内存) 输入设备 输出设 ...

  8. 不依赖Python第三方库实现梯度下降

    认识 梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模), 我感觉, 其实就是偏导数向量方向 ...

  9. 详解Linux系统中10个最危险的命令

    概述 大多数的朋友都是主要用的windows系统,基本用鼠标就可以完成所有的操作,但是在Linux系统中很多都是键盘+命令操作电脑的,Linux命令行使用很有趣,但有时候也很危险,尤其是在你不确定你自 ...

  10. Python入门篇-装饰器

    Python入门篇-装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.装饰器概述 装饰器(无参) 它是一个函数 函数作为它的形参 返回值也是一个函数 可以使用@functi ...