求助
查看原帖
求助
72419
w4p3r楼主2021/1/7 20:13

本人的思路是挨次选出当前SG函数最小的集合,保证选出的集合一定都包含1,2或都不包含1,2,本人觉得这种思路应该没有问题,但是连样例都过不了。

(类似于小粉兔题解的思路,只不过对于1,2不在集合时也进行正常的状压DP)

有大佬帮我指出我思路/代码的问题嘛/kel(代码多半没问题,我对着看差不多一个小时了)

//W4P3R
#include<bits/stdc++.h>
#define inf 1e9
#define eps 1e-6
#define mp make_pair
#define pb push_back
#define re register int
#define fr first
#define sd second
#define pa pair<int,int>
#define FOR(i,a,b) for(re i=a;i<=b;i++)
#define REP(i,a,b) for(re i=a;i>=b;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define N 16
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
inline ll read()
{
	char ch=getchar();
	ll s=0,w=1;
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
	return s*w;
}
inline int lowbit(int x){return x&(-x);}
int n,m;
int b[N][N],A[N][1<<N],g[1<<N],f[1<<N];
int bit[1<<N],Q[1<<N],P[N*N];
const int mod=1e9+7;
inline int Z(int x){return (x>=mod?x-mod:x);}
inline int calc(int S,int T)
{
	int ans=1;if(!T)return ans;
	FOR(i,1,n)if((S>>(i-1))&1)ans=1LL*ans*Z(P[A[i][T]]+mod-1)%mod;
	return ans;
}//S中每个点都至少向T中连一条边的方案数
int main()
{
	//ios::sync_with_stdio(false);
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	n=read(),m=read();
	FOR(i,1,m)b[read()][read()]=1;
	FOR(i,1,(1<<n)-1)bit[i]=bit[i>>1]+(i&1);
	P[0]=1;
	FOR(i,1,m)P[i]=Z(P[i-1]+P[i-1]);
	FOR(i,1,n)Q[1<<(i-1)]=i;
	FOR(x,1,n)
	{
		FOR(S,1,(1<<n)-1)
		{
			if(bit[S]==1)A[x][S]=b[x][Q[S]];
			else A[x][S]=A[x][S-lowbit(S)]+b[x][Q[lowbit(S)]];
		}
	}//A[x][S]表示x到集合S的边数
	f[0]=1;//f[S]表示现在已经确定SG函数的集合S
	FOR(S,1,(1<<n)-1)
	{
		int t1=(S&1),t2=(S>>1)&1;
		if(t1^t2)continue;
		int U=(1<<n)-1,T;
		for(T=(S-1)&S;;T=(T-1)&S)
		{
			int V=S^T;
			       f[S]=Z(f[S]+1LL*f[T]*calc(U^S,V)%mod);
			if(!T)break;
		}
	}
	cout<<Z(P[m]+mod-f[(1<<n)-1])<<'\n';
	return 0;
}
//gl

(本人输出答案大于样例,即DP到的方案数少了)

2021/1/7 20:13
加载中...