【agc016_f】

题目大意

给你一个DAG,边只从编号小的点连到大的点。给你两个棋子一个在1号一个在2号,小A(先手)和小B轮流进行操作:把一个棋子沿着边(x,y)从x移到y。不能操作者输。问原图有多少个子图满足小A必胜。
n<=15

解题思路

首先辨认出是个组合游戏,那么考虑使用SG函数。
我们想要知道有多少种方案sg[1]!=sg[2]。那么我们可以统计sg[1]=sg[2]的然后再减掉。
一种可行的暴力是我把点按sg值分层,然后逐层dp,这样的复杂度稍微有点大。
考虑另一种dp。我们设f[s]表示在考虑了集合s这些点后,保证sg[1]=sg[2]的方案数。(可以没有12,那就相当于12没有边)
我们按照分层的思路,看看能不能在s的底部再垫一层点,这样s的所有点sg值都会变大1。
这是可行的,于是我们子集dp,考虑s的子集t,s-t的点都要向t连至少一条边,s-t的点之间可以随便连,t的点可以和s-t随便连,但是不能连回t。那么这样就可以转移了,第一、三部分方案数可以预处理一个数组,第二部分就是f[s-t]了。
注意枚举子集的时候1和2不能属于不同层。
时间复杂度O(n*3^n)

代码

#include<cstdio> 
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
#define cmax(a,b) (a=(a>b)?a:b)
#define cmin(a,b) (a=(a<b)?a:b)
typedef long long ll;
const int N=1e6+5,M=2e6+5,mo=1e9+7;
int n,m,x,y,ts,s1,s,ns,p,ans,f[1<<16],cnt[16][1<<16],i;
ll inc;
int tt,b[1000],nxt[1000],fst[1000];
void cr(int x,int y)
{
    tt++;
    b[tt]=y;
    nxt[tt]=fst[x];
    fst[x]=tt;
}
int main()
{
    freopen("t6.in","r",stdin);
    //freopen("t6.out","w",stdout);
    scanf("%d %d",&n,&m);
    fo(i,1,m)
    {
        scanf("%d %d",&x,&y);
        cr(x,y);
    }
    ts=1<<n;ts--;
    fo(i,1,n) fo(s,0,ts) 
        for(p=fst[i];p;p=nxt[p]) if ((1<<b[p]-1)&s) cnt[i][s]++;
    fo(s,0,ts)
    if ((s&1)==((s>>1)&1))
    {
        f[s]=1;
        for(ns=(s-1)&s;ns;ns=(ns-1)&s)
            if ((ns&1)==((ns>>1)&1))
            {
                s1=s-ns;
                inc=f[s1];
                fo(i,1,n) 
                if (s1&(1<<i-1))
                    (inc*=(1<<cnt[i][ns])-1)%=mo;
                else if (ns&(1<<i-1))
                    (inc<<=cnt[i][s1])%=mo;
                f[s]=(f[s]+inc)%mo;
            }
    }
    ans=1;
    fo(i,1,m) ans=ans*2%mo;
    ans-=f[ts];
    ans=(ans+mo)%mo;
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值