bzoj3195: [Jxoi2012]奇怪的道路

又是被锤烂的一天,特别是xgc,天天踩爆我还在我身边吹比,你们去看看他的blog就知道了(埋头苦干)

这道题应该这样来考虑,每次加入一个点,然后去前面k个点进行连边

需要考虑的是这个点连出多条边时,顺序不同但是本质相同的问题

我们需要强制对于每个本质不同的方案只被某一种顺序产生贡献一次

改变枚举顺序,先枚举和当前点连的另一个点,然后再枚举次数,这样连接点按小到大的顺序了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1000000007;

LL f[50][50][1100];
int main()
{
    int n,m,k,li;
    scanf("%d%d%d",&n,&m,&k);k=min(k+1,n),li=(1<<k)-1;
    memset(f,0,sizeof(f));f[1][0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int u=max(0,k-i);u<k-1;u++)
            for(int j=0;j<m;j++)
                for(int zt=0;zt<=li;zt++)
                    if(f[i][j][zt])
                    {
                        int nt=(zt^(1<<u)^(1<<k-1));
                        f[i][j+1][nt]=(f[i][j+1][nt]+f[i][j][zt])%mod;
                    }
        for(int j=0;j<=m;j++)
            for(int zt=0;zt<=li;zt++)
                if(!(zt&1))f[i+1][j][zt>>1]=(f[i+1][j][zt>>1]+f[i][j][zt])%mod;
    }
    printf("%lld\n",f[n][m][0]);
    
    return 0;
}

 

转载于:https://www.cnblogs.com/AKCqhzdy/p/10401491.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值