Live2d Test Env

luoguP2768: 珍珠项链(矩阵乘法优化DP)

题意:有K种珍珠,每种N颗,求长度为1~N的项链,包含K种珍珠的项链种类数。N<=1e9, K<=30;

思路:矩阵快速幂,加个1累加前缀和即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,w,v) for(int i=w;i<=v;i++)
using namespace std;
const int Mod=1234567891;
struct mat{
    ll a[32][32];int len;
    mat(){
        rep(i,0,31) rep(j,0,31) a[i][j]=0;
    }
    mat friend operator *(mat m,mat n)
    {
        mat res; res.len=m.len;
        rep(k,0,res.len)
         rep(i,0,m.len)
          rep(j,0,n.len) {
              (res.a[i][j]+=1LL*m.a[i][k]*n.a[k][j]%Mod)%=Mod;
        }
        return res;
    }
    mat friend operator ^(mat m,int K){
        mat res; res.len=m.len;
        rep(i,1,res.len) res.a[i][i]=1;
        while(K){
            if(K&1) res=res*m;
            m=m*m; K>>=1;
        }
        return res;
    }
};
int main()
{
    int T,N,K;
    scanf("%lld",&T);
    while(T--){
       scanf("%d%d",&N,&K);
       mat base,a,res;
       base.len=K+1; a.len=K+1; res.len=K+1;
       a.a[0][0]=1;
       base.a[K+1][K]=1;  base.a[K+1][K+1]=1;
       rep(i,1,K){
         base.a[i][i]=i,
         base.a[i][i-1]=K-i+1;
       }
       res=(base^(N+1))*a;
       printf("%lld\n",res.a[K+1][0]);
    }
    return 0;
}

 

posted @ 2019-07-16 17:26  nimphy  阅读(298)  评论(0编辑  收藏  举报