[BZOJ3195] [Jxoi2012]奇怪的道路

[BZOJ3195] [Jxoi2012]奇怪的道路

图论是不可能的

题目限定了距离,所以直接按点编号的顺序dp下来,记录连了几条边,之前的点每个点的所连边数是不是奇数

每个点转移时就是向之前的点连边,保证最后能连的边连完每个点都满足条件即可

 

const int N=80,P=1000000007;
 
 
int n,m,k;
 
ll dp[31][1<<8][31];
ll C[N][N];
 
 
 
int main(){
    n=rd(),m=rd(),k=rd();
    k=min(k,n);
    C[0][0]=1;
    rep(i,1,N-1) {
        C[i][0]=1;
        rep(j,1,N-1) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
    }
    dp[0][0][0]=1;
    rep(i,1,k-1) {
        int A=(1<<i)-1;
        rep(S,0,A) {
            int t=0;
            rep(j,0,i-1) if(S&(1<<j)) t++;
            rep(R,0,A) {
                int NS=(S^R)|((t&1)<<i);
                rep(j,0,m) {
                    for(reg int d=j+t;d<=m;d+=2) {
                        (dp[i][NS][d]+=C[(d-j-t)/2+i-1][i-1]*dp[i-1][R][j]%P)%=P;
                    }
                }
            }
        }
    }
    int A=(1<<k)-1;
    rep(i,k,n-1) {
        rep(S,0,A) {
            int t=0;
            rep(j,0,k-1) if(S&(1<<j)) t++;
            rep(R,0,A) if((R&1)==(S&1)) { // 保证最前面那个点连完之后是偶数
                int NS=((S^R)>>1)|((t&1)<<(k-1));
                rep(j,0,m) {
                    for(reg int d=j+t;d<=m;d+=2) {
                        (dp[i][NS][d]+=C[(d-j-t)/2+k-1][k-1]*dp[i-1][R][j]%P)%=P;
                    }
                }
            }
        }
    }
    ll ans=dp[n-1][0][m];
    printf("%lld\n",ans);
}
 
 
posted @ 2019-10-13 10:16  chasedeath  阅读(93)  评论(0编辑  收藏  举报