zoukankan      html  css  js  c++  java
  • BZOJ2004: [Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    这个状压状态时显然的,但是总状态数有 $inom{K}{P}$.  

    好在题目中有一个要求,就是每个格子必须经过一次,所以说我们压缩的长度为 $P$ 的状态中首位必为 1.  

    那么状态数就减小为 $inom{K-1}{P-1}$,来一个矩阵乘法就行了. 

    code: 

    #include <cstdio> 
    #include <algorithm> 
    #include <cstring>   
    #define ll long long 
    #define mod 30031  
    #define N 303    
    #define setIO(s) freopen(s".in","r",stdin)  
    using namespace std; 
    int cnt[1<<12],mark[1<<12],idx[1<<12];
    struct M 
    {  
        int m[130][130];         
        M(int t=0) 
        {
            memset(m,0,sizeof(m));   
            for(int i=1;i<130;++i) m[i][i]=t;   
        }
        int *operator[](int x) { return m[x]; }     
        M operator*(const M b) const 
        {      
            M c(0);   
            for(int i=1;i<130;++i) 
                for(int j=1;j<130;++j)  
                    for(int k=1;k<130;++k)  
                        (c[i][j]+=(ll)m[i][k]*b.m[k][j]%mod)%=mod;   
            return c;   
        }   
        friend M operator^(M a,int k)  
        {
            M tmp(1);   
            while(k) 
            {
                if(k&1) tmp=tmp*a;   
                a=a*a,k>>=1;  
            }
            return tmp;  
        }
    }v,A;  
    int main() 
    { 
        // setIO("input"); 
        int n,K,P,cn=0;  
        scanf("%d%d%d",&n,&K,&P);          
        for(int i=1;i<(1<<P);++i) 
        {
            cnt[i]=cnt[i-(i&(-i))]+1;            
            if(cnt[i]==K&&(i&(1<<(P-1)))) mark[i]=1,idx[i]=++cn;                 
        }   
        for(int i=1;i<(1<<P);++i) 
        {
            if(!mark[i])  continue;    
            if(i&1)  v[idx[i]][idx[(i>>1)|(1<<(P-1))]]=1;       
            else 
            {               
                for(int j=0;j<P;++j)  
                    if(i&(1<<j))       
                        v[idx[i]][idx[((i^(1<<j))>>1)|(1<<(P-1))]]=1;   
            }
        }    
        A=v^(n-K);       
        int an=idx[(1<<P)-(1<<(P-K))];    
        printf("%d
    ",A[an][an]);  
        return 0; 
    }
    

      

  • 相关阅读:
    Canvas中的save方法和restore方法
    python之函数默认参数的坑
    python之函数名的应用
    python之golbal/nonlocal
    python之*的魔性用法
    python之函数的传参形参的第三种动态参数*args和**kwargs
    python之道09
    python之函数的初识
    python之道08
    python之99乘法表
  • 原文地址:https://www.cnblogs.com/guangheli/p/13029827.html
Copyright © 2011-2022 走看看