[SNOI2019] card

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!

Guess you like

Origin www.cnblogs.com/PaperCloud/p/11221366.html