• AT2390 Games on DAG


    AT2390 Games on DAG

    题意

    (1,2) 号点各一个石头,每次沿边移动一个石头,不能动者输。求所有连边子集中先手胜的情况。

    思路

    发现对于两个石头的 SG 函数是独立的,输者两个石头 SG 函数异或值为 0,那么先手胜的情况就是所有情况减去这种情况。

    对于所有 SG 函数为 (v) 的点,它们必须向 SG 函数小于 (v) 的所有点连至少一条边,对大于 (v) 的连边没有约束,并且互相不能连边。

    所以我们可以枚举当前图的 SG 函数为 0 的点,这样所有其他点都至少向它们连一条边,而它们之间不连边,它们向其他点连边任意。于是对于剩下点的连通子图,我们又可以将所有点的 SG 函数减 1,使它又可以枚举 SG 函数为 0 的点。

    于是我们可以 DP。设 (f_S(1,2in S)) 为对于 (S) 所有连通子图满足 1,2 SG 函数相等的方案数。

    转移时枚举 (S) 的子集 (T),使 (1,2in T)(1,2 ot in T)。对于前者情况,(T) 对于 (S) 的补集为 SG 函数为 0 的点,从 (f_T) 转移即可。对于后者情况,1,2 SG 函数为 0,(T) 中的边随便连。

    DP 前预处理出所有集合对每个点的连边条数。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=x*10+(c^48),c=getchar();
    	return w?-x:x;
    }
    namespace star
    {
    	const int maxn=15,mod=1e9+7;
    	int n,m,a[maxn][maxn],f[1<<maxn],c[1<<maxn][maxn],pow[maxn*maxn];
    	inline void work(){
    		n=read(),m=read();
    		pow[0]=1;for(int i=1;i<=m;i++) pow[i]=(pow[i-1]<<1)%mod;
    		for(int x,y,i=1;i<=m;i++) x=read()-1,y=read()-1,a[x][y]=1;
    		for(int d=1;d<1<<n;d++){
    			int j=0;
    			while(~d>>j&1)++j;
    			for(int x=0;x<n;x++) c[d][x]=c[d^1<<j][x]+a[x][j];
    		}
    		for(int d=0;d<1<<n;d++) if((d&3)==3){
    			f[d]=1;
    			for(int t=d&(d-1);t;--t&=d) if((t&1)==(t>>1&1)) if(t&1){
    				int res=1;
    				for(int i=0;i<n;i++) if(t>>i&1) res=1ll*res*(pow[c[d^t][i]]-1)%mod;
    				else if(d>>i&1) res=1ll*res*pow[c[t][i]]%mod;
    				f[d]=(f[d]+1ll*res*f[t])%mod;
    			}else{
    				int res=1;
    				for(int i=0;i<n;i++) if(t>>i&1) res=1ll*res*(pow[c[d^t][i]]-1)%mod*pow[c[t][i]]%mod;
    				else if(d>>i&1) res=1ll*res*pow[c[t][i]]%mod;
    				f[d]=(f[d]+res)%mod;
    			}
    		}
    		printf("%d
    ",(pow[m]-f[(1<<n)-1]+mod)%mod);
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    
  • 相关阅读:
    布局神器display:table-cell
    解决IE兼容总汇【转】
    jQuery Validate【强大的表单验证】
    使用信号SIGALRM 为 recvfrom 设置超时,防止死等待
    并发服务器(IO多路复用)
    并发服务器(多进程版本)
    TCP listen()函数内幕
    c++ 重载运算符规则
    内核定时器struct timer_list
    C和arm汇编的相互调用(看书笔记)
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/14505362.html
Copyright © 2020-2023  润新知