给出一些点集,然后对于每一次要求给出的这些点集里的1,2,3,4,5,6....n/2的匹配数,
dp[i][j] 表示到第i次操作里点集为j的匹配数,然后我每次加入一条边u-v,我的状态就是
dp[i][j] = dp[i-1][j] + dp[i-1][(不含u,v)的j],删除就是dp[i][j] = dp[i-1][j] - dp[i-1][(不含u,v)的j]
一个匹配就是两个点,所以2*i个点的答案就是匹配为i的答案。
然后可以减去一维,变成一维的dp,然后在取模一下就可以了
#include<map> #include<set> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define lowbit(x) (x & (-x)) typedef unsigned long long int ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 1050; const int maxm = 10000007; const int mod = 1e9+7; using namespace std; int n, m, tol, T; int dp[maxn]; int cnt[maxn]; int ans[20]; void init() { memset(dp, 0, sizeof dp); } int calc(int x) { int ans = 0; while(x) { if(x & 1) ans++; x >>= 1; } return ans; } void handle() { for(int i=1; i<=(1<<10); i++) { cnt[i] = calc(i); } } int main() { handle(); scanf("%d", &T); while(T--) { init(); scanf("%d%d", &n, &m); dp[0] = 1; char s[10]; while(m--) { memset(ans, 0, sizeof ans); int u, v; scanf("%s%d%d", s, &u, &v); u--, v--; int y = (1<<u) + (1<<v); if(s[0] == '+') { for(int i=(1<<n)-1; i>=0; i--) { if((i&(1<<u)) && (i&(1<<v))) { dp[i] += dp[i-y]; dp[i] %= mod; } } } else { for(int i=0; i<(1<<n); i++) { if((i&(1<<u)) && (i&(1<<v))) { dp[i] -= dp[i-y]; dp[i] = (dp[i] % mod + mod) % mod; } } } for(int i=0; i<(1<<n); i++) { ans[cnt[i]] += dp[i]; ans[cnt[i]] = (ans[cnt[i]] % mod + mod) % mod; } for(int i=2; i<=n; i+=2) printf("%d%c", ans[i] % mod, i==n ? ' ' : ' '); } } return 0; }