畫家小P

集訓隊論文
太長不看版:
預處理每個colcol構成的2n2^n個集合的答案後3ndp3^ndp出一個連通塊的容斥係數,再i=1n2i13ni\sum_{i=1}^n 2^{i-1}3^{n-i}的複雜度做一個33進制子集dpdp出整個圖的容斥係數。
論文複雜度計算有問題:
實際複雜度爲:
在這裏插入圖片描述
哦,還要乘個nn

#include<bits/stdc++.h>
#define LL long long
#define mod 998244353
using namespace std;

int n,m,N,fe[1<<16],fn[1<<16],rc[1<<16],bit[1<<16],lg[1<<16],c[16],rk[16],f[43046722],pw[16],am[16],st[1<<16];
LL C,a[16],ar[16],pw2[66];
bool cmp(const int &u,const int &v){ return a[u] < a[v]; }

int upd(int a){ return a >= mod ? a - mod : a; }
int Sol(LL C){
	if(C > ar[ar[0]] && ((C ^ ar[ar[0]]) > ar[ar[0]])) return 0;
	if(ar[ar[0]] == 0) return 1;
	LL t = 1ll << (upper_bound(pw2,pw2+60,ar[ar[0]]) - pw2 - 1);
	int dp[2][2]={};
	int now = 1, pre = 0;
	dp[now][0] = 1;
	for(int i=1;i<ar[0];i++){
		swap(now,pre);
		if(ar[i] >= t){
			dp[now][0] = (dp[pre][0] * 1ll * (t % mod) + dp[pre][1] * 1ll * ((ar[i] - t + 1) % mod)) % mod;
			dp[now][1] = (dp[pre][1] * 1ll * (t % mod) + dp[pre][0] * 1ll * ((ar[i] - t + 1) % mod)) % mod;
		}
		else{
			dp[now][0] = dp[pre][0] * 1ll * ((ar[i] + 1) % mod) % mod;
			dp[now][1] = dp[pre][1] * 1ll * ((ar[i] + 1) % mod) % mod;
		}
	}
	int r = (C >= t ? dp[now][1] : dp[now][0]);
	C ^= t;
	ar[ar[0]] ^= t;
	for(int i=ar[0]-1;i>=1;i--)
		if(ar[i] > ar[i+1]) swap(ar[i] , ar[i+1]);
		else break;
	return upd(r + Sol(C));
}

int main(){ 
	scanf("%d%d%lld",&n,&m,&C);N=1<<n;
	pw2[0] = 1;
	for(int i=1;i<=60;i++) pw2[i] = 1ll << i;
	for(int i=0;i<n;i++) scanf("%lld",&a[i]) , lg[1<<i] = i , c[i] = i;
	sort(c,c+n,cmp);
	for(int i=0;i<n;i++) rk[c[i]] = i;
	sort(a,a+n);
	for(int i=0;i<n;i++) am[i] = (a[i] + 1) % mod;
	for(int u,v;m--;){ 
		scanf("%d%d",&u,&v);
		u = rk[u-1] , v = rk[v-1];
		fe[1<<u|1<<v] = 1;
	}
	for(int i=0;i<n;i++) for(int j=0;j<N;j++) if(j>>i&1)
		fe[j] |= fe[j-(1<<i)];
	for(int i=0;i<N;i++) bit[i] = bit[i>>1] + (i&1);
	int tN = 1;
	pw[0] = 1;
	for(int i=1;i<=n;i++) pw[i] = tN = 3 * tN;
	for(int j=1;j<N;j++){
		rc[j] = !fe[j];
		for(int i=(j-1)&j;i;i=(i-1)&j) if(i&(j&-j))
			rc[j] = (rc[j] - rc[i] * (!fe[j-i])) % mod;
		st[j] = st[j-(j&-j)] + pw[lg[j&-j]];
	}
	for(int j=1;j<N;j++) if(bit[j] & 1){
		st[j] += pw[lg[j&-j]];
	}
	for(int j=1;j<N;j++)
		if(!(bit[j] & 1))
			rc[j] = 1ll * rc[j] * am[lg[j&-j]] % mod;
	if(!C) fn[0] = 1;
	for(int j=1;j<N;j++){
		ar[0] = 0;
		for(int i=0;i<n;i++) if(j>>i&1) 
			ar[++ar[0]] = a[i];
		fn[j] = Sol(C);
	}
	f[0] = 1;
	int ans = 0;
	for(int i=0;i<tN;i++) if(f[i]){
		static int ar[16] , cnt = 0;
		int hsta = 0;
		cnt = 0;
		for(int j=0;j<n;j++) if(i / pw[j] % 3 == 0) 
			ar[cnt++] = j , hsta |= 1 << j;
		if(cnt){
			int rsta = hsta - (1<<ar[0]) , vp = 1<<ar[0];
			for(int j=rsta;;j=(j-1)&rsta){
				int nsta = i + st[j | vp];
				f[nsta] = (f[nsta] + f[i] * 1ll * rc[j|vp]) % mod;
				if(!j) break;
			}
		}
		else{
			int psta = 0;
			for(int j=0;j<n;j++)
				if(i / pw[j] % 3 == 2)
					psta |= 1 << j;
			ans = (ans + f[i] * 1ll * fn[psta]) % mod;
		}
	}
	printf("%d\n",(ans+mod)%mod);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章