【BZOJ 2004】: [Hnoi2010]Bus 公交线路

题目链接:

  TP

题解:

    所以说,超显眼的数据范围啊。

  很显然我们对于每个P的区间都是要有k个站被bus停留,然后考虑转移的话应该是把这k个站里的某个bus往前走,那么转移也很显然了,n的范围很大,所以直接上矩阵。

代码:

#define Troy 

#include <bits/stdc++.h>

using namespace std;

inline int read(){
    int s=0,k=1;char ch=getchar();
    while(ch<'0'|ch>'9')    ch=='-'?k=-1:0,ch=getchar();
    while(ch>47&ch<='9')    s=s*10+(ch^48),ch=getchar();
    return s*k;
}

const int N=129,mod=30031;

int n,k,p,BGM,stk[N],m;

struct Matrix{
    int a[N][N];
    Matrix(){memset(a,0,sizeof(a));}
    inline void evoid(){
        for(int i=0;i^m;++i)
            a[i][i]=1;
    }
    inline friend Matrix operator *(const Matrix &x,const Matrix &y){
        Matrix c;
        for(int i=0;i^m;++i)
            for(int j=0;j^m;++j)
                for(int k=0;k^m;++k)
                    c.a[i][j]=(c.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
        return c;
    }
    inline friend Matrix operator ^(Matrix x,int b){
        Matrix ret;ret.evoid();
        while(b){
            if(b&1)ret=ret*x;
            b>>=1;x=x*x;
        }return ret;
    }
};

inline bool move_to(int to,int from){
    from^=1<<p-1;
    from<<=1;
    int deta=from^to;
    return (deta&(-deta))==deta;
}

int main(){
    n=read(),k=read(),p=read();
    register int i,j;    
    for(i=(1<<p-1);i^(1<<p);++i){
        int x=i;
        for(j=0;x;x^=(x&(-x)),++j);
        if(j==k){
            if(i==(1<<p)-(1<<p-k))
                BGM=m;
            stk[m++]=i;
        }
    }
    Matrix ans,t;
    ans.a[BGM][0]=1;
    for(i=0;i^m;++i)
        for(j=0;j^m;++j){
                t.a[i][j]=move_to(stk[j],stk[i]);
        }
    ans=(t^(n-k))*ans;
    printf("%d\n",ans.a[BGM][0]);
}

 

posted @ 2017-10-31 21:38  Troywar  阅读(232)  评论(0编辑  收藏  举报