题解:P11714 [清华集训 2014] 主旋律
Solution
DAG 计数模板题。
考虑算出
设内部有
根据经典套路,对零度点进行容斥,容斥系数为
按照
则有:
以及
注意,第一遍计算
直接做是
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=15+5,MAXM=100000+10,MOD=1e9+7;
int n,m,e[MAXN][MAXN],pw[MAXN*MAXN],dp[MAXM],ori[MAXM],nb[MAXN],mul[MAXM];
int calc(int s1,int s2) {
int cnt=0;
ffor(i,1,n) if(s1&(1<<i-1)) cnt+=__builtin_popcountll(nb[i]&s2);
return pw[cnt];
}
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
ffor(i,1,m) {int u,v;cin>>u>>v,e[u][v]=1,nb[u]|=(1<<v-1);}
pw[0]=dp[0]=ori[0]=1;
ffor(i,1,m) pw[i]=pw[i-1]*2%MOD;
ffor(i,1,(1<<n)-1) {
int c=0;
vector<int> pos;
ffor(j,1,n) if(i&(1<<j-1)) pos.push_back(j);
for(auto p1:pos) for(auto p2:pos) c+=e[p1][p2];
for(int S=i;S;S=(S-1)&i) if((S&-S)==(i&-i)) mul[i]=(mul[i]-dp[S]*mul[i-S])%MOD;
dp[i]=ori[i]=pw[c];
for(int S=i;S;S=(S-1)&i) dp[i]=(dp[i]+mul[S]*ori[i-S]%MOD*calc(S,i-S))%MOD;
mul[i]=(mul[i]-dp[i])%MOD;
}
cout<<(dp[(1<<n)-1]%MOD+MOD)%MOD;
return 0;
}