[JZOJ5836] Sequence

Problem

题目链接

Solution

吼题啊吼题!

首先如何求本质不同的子序列个数就是 \(f[val[i]]=1+\sum\limits_{j=1}^k f[j]\)

其中 \(f[i]\) 表示的是以 \(i\) 结尾的子序列个数

先把原数列的不同子序列个数求出来,然后观察一下这个转移,贪心的发现每次都是选一个最早出现的 \(i\) 填到序列末尾,然后更新这个值。

所以填的部分一定是 \(\frac mk\)\(K\) 的排列,还有多出来了 \(m\%k\) 个元素暴力填进去。

\(K\) 个元素的转移是一样的,可以拿矩乘做。然后多余的部分求前缀积暴力求就行了。

Code

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cctype>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using std::min;
using std::max;
using std::swap;
using std::vector;
const int N=105;
const int M=1e6+5;
typedef double db;
typedef long long ll;
#define int long long
const int mod=1e9+7;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define mp(A,B) std::make_pair(A,B)

int n,m,k,per[M];
int val[M];pii las[M];

struct Mat{
    int a[N][N];

    void clear(){
        memset(a,0,sizeof a);
    }

    void init(){
        clear();
        for(int i=1;i<=k+1;i++)
            a[i][i]=1;
    }

    void print(){
        for(int i=1;i<=k+1;i++,puts(""))
            for(int j=1;j<=k+1;j++)
                printf("%lld ",a[i][j]);
    }

    friend Mat operator*(Mat x,Mat y){
        Mat z;z.clear();
        for(int i=1;i<=k+1;i++){
            for(int p=1;p<=k+1;p++){
                for(int j=1;j<=k+1;j++)
                    z.a[i][j]=(z.a[i][j]+x.a[i][p]*y.a[p][j]%mod)%mod;
            }
        } return z;
    }
}cs,f,qzh[N];

int getint(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch))w|=ch=='-',ch=getchar();
    while( isdigit(ch))X=X*10+ch-48,ch=getchar();
    if(w) return -X;return X;
}

Mat ksm(Mat x,int y){
    Mat ans;ans.init();
    while(y){
        if(y&1) ans=ans*x;
        x=x*x;y>>=1;
    } return ans;
}

signed main(){
    freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);
    n=getint(),m=getint(),k=getint();
    int sum=0;f.clear();f.a[1][k+1]=1;
    for(int i=1;i<=k;i++) las[i]=mp(0,i);
    for(int i=1;i<=n;i++){
        val[i]=getint();
        int p=f.a[1][val[i]];
        f.a[1][val[i]]=(sum+1)%mod;
        sum-=p;sum+=f.a[1][val[i]];sum%=mod;
        las[val[i]]=mp(i,val[i]);
    } std::sort(las+1,las+1+k);
    qzh[0].init();
    for(int i=1;i<=k;i++){
        per[i]=las[i].second;
        qzh[i].clear();
        for(int j=1;j<=k+1;j++) qzh[i].a[j][j]=1;
        for(int j=1;j<=k+1;j++) qzh[i].a[j][per[i]]=1;
        qzh[i]=qzh[i-1]*qzh[i];
    } cs=ksm(qzh[k],m/k);
    cs=cs*qzh[m%k];
    f=f*cs;int ans=0;
    for(int i=1;i<=k;i++) (ans+=f.a[1][i])%=mod;
    printf("%lld\n",ans);
    return 0;
}
posted @ 2018-10-12 21:58  YoungNeal  阅读(218)  评论(0编辑  收藏  举报