【BZOJ2560】串珠子

广告:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44060425");
}

题解:

gi 表示状态为i时随便连边时的方案个数
fi 表示状态为i时图是连通图的方案个数

gi 好求,直接枚举一个里面的点 a ,然后向外面某点b连边得到 gi|(1<<b)
然后我们可以在从 gi 中减去某些东西得到 fi
先确定一个小的连通块,状态为a,然后其它点的状态就是i^a
然后显然 ga×fi xor a 就是要减去的。
确定一个点x,然后以此为基础枚举连通块就好了。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MOD 1000000007
#define N 20
#define M 101000
using namespace std;
int n,S,a[N][N];
long long f[M],g[M];

int main()
{
    int i,j,k,now;
    scanf("%d",&n);
    for(i=0;i<n;i++)for(j=0;j<n;j++)scanf("%d",&a[i][j]);
    S=1<<n;
    for(i=1;i<S;i++)
    {
        g[i]=1;
        for(j=0;j<n;j++)if(i&(1<<j))
            for(k=j+1;k<n;k++)if(i&(1<<k))
                g[i]=g[i]*(a[j][k]+1)%MOD;
        f[i]=g[i];
        for(j=n-1;j+1;j--)
            if(i&(1<<j)){now=j;break;}
        now=i^(1<<now);
        for(j=now;j;j=(j-1)&now) // 枚举子集
            f[i]=(f[i]-g[j]*f[i^j]%MOD+MOD)%MOD;
    }
    cout<<f[S-1];
}

Qwq

今天下午怎么突然好困。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值