Portal
Description
There are a deck of cards. There are brand \ (n \) species are labeled \ (1, 2, ..., the n-\) , each with its \ (C \) sheets. So the deck a total of \ (nC \) sheets.
Card three consecutive numbers ( \ (I, I +. 1, I + 2 \) ) or three identical tiles \ ((i, i, i ) \) may be composed of a stack. If a set of cards may be divided into a number (including zero) stack, to a group called ace .
You touch a card from the pile some initial cards. Now you want to pick out some of the cards form a group of ace, ace might ask how many composed it? The answer to \ (998 244 353 \) modulo.
Two identical cards if and only if they contain the quantity of each card are the same.
Solution
This question is found in the \ (n \) is large, so consider matrix multiplication
I found \ ((i, i + 1 , i + 2) \) such cards, the same \ (I \) , at most two overlapping
So consider a \ (3 * 3 \) state indicates the current number \ (I \) and \ (i-1 \) the initial quantity of Junko \ ((0,1,2) \)
Consider how the conversion to the next number, find it necessary to enumerate \ (i + 1 \) the number of straight start, it will take on a viable \ ((i + 1, i + 1, i + 1) \) number number
The original title of \ (dp \) converted bit matrix multiplication
For several already have initial license, we consider separate out transfer
The transition matrix can first calculated power, constant reduced
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 from PaperCloud , without permission, please do not reprint, TKS!