BZOJ 5298: [Cqoi2018]交错序列 二项式定理+矩阵乘法

code:

#include <cstdio> 
#include <cstring>   
#include <algorithm> 
#define M 185   
#define N 10000008   
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std; 
int B,mod,n,a0,b1,C[M][M],powv[M];      
struct matrix 
{      
    int v[M][M];  
    matrix() { memset(v,0,sizeof(v)); }   
    int *operator[](int x) { return v[x]; }                         
    matrix operator*(matrix b) const 
    {
        matrix c;     
        int i,j,k,sum;  
        for(i=0;i<B;++i) 
            for(j=0;j<B;++j) 
            {   
                ll sum=0;  
                for(k=0;k<B;++k)
                    sum+=(ll)v[i][k]*b[k][j];   
                sum%=mod; 
                (c[i][j]+=sum)%=mod;     
            }
        return c;   
    }    
}ma,ans;              
int main() 
{   
    // setIO("input"); 
    int i,j;             
    scanf("%d%d%d%d",&n,&a0,&b1,&mod);     
    int c=a0+b1+1;  
    B=2*c;   
    C[0][0]=1;     
    for(i=1;i<M;++i) 
    {
        C[i][0]=1;   
        for(j=1;j<=i;++j) 
        {
            C[i][j]=(ll)(C[i-1][j]+C[i-1][j-1])%mod;    
        }
    }
    powv[0]=1;
    for(i=1;i<=a0;++i) powv[i]=(ll)powv[i-1]*n%mod;
    for(i=0;i<c;++i) 
    {
        ma[i][i]=1;     
        ma[i+c][i]=1;    
        for(j=i;j<c;++j) ma[i][j+c]=C[j][i];     
    } 
    // ans[0][0]=1;   
    for(i=0;i<B;++i) ans[i][i]=1;  
    while(n) 
    {
        if(n&1)     ans=ans*ma;    
        ma=ma*ma;  
        n>>=1;  
    }
    int res=0;
    for(int i=0;i<=a0;++i){
        int p=a0+b1-i;
        int fac=1ll*C[a0][i]*((a0-i)&1?mod-1:1)%mod*powv[i]%mod;
        int cnt=1ll*(ans[0][p]+ans[0][p+c])%mod;
        res=1ll*(res+1ll*cnt*fac%mod)%mod;   
    }
    printf("%d
",(res+mod)%mod);     
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12251339.html