集訓隊論文
太長不看版:
預處理每個構成的個集合的答案後出一個連通塊的容斥係數,再的複雜度做一個進制子集出整個圖的容斥係數。
論文複雜度計算有問題:
實際複雜度爲:
哦,還要乘個
#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);
}