Solution P10813 | He was My Friend
一个经典 trick:考虑值域为
发现非常简单粗暴:可以直接枚举
在值域变大的情况下,我们可以将其拆成多个值域为
设
利用高维前缀和可以做到
令
可以算
时间复杂度
ll n,V,m,p[505],q[505],f[20][1<<18],w[20];
bool vis[1<<18], t[30];
void addmod(ll &x){ if(x >= mod) x -= mod; }
void solve(){
n=read(), V=read(), m=read();
for(ll i=1;i<=m;i++){
p[i]=read()-1, q[i]=read()-1;
}
for(ll i=0;i<(1<<n);i++){
for(ll j=0;j<n;j++) t[j]=((i>>j)&1);
for(ll j=1;j<=m;j++){
if(t[p[j]] > t[q[j]]) swap(t[p[j]], t[q[j]]);
}
vis[i] = 1;
for(ll j=1;j<n;j++) if(t[j-1] > t[j]) vis[i]=0;
}
f[0][0] = 1;
for(ll i=1;i<=n;i++){
for(ll j=0; j<(1<<n); j++) f[i][j] = f[i-1][j];
for(ll j=0; j<n; j++)
for(ll k=0; k<(1<<n); k++){
if((k>>j)&1) continue;
addmod(f[i][k^(1<<j)] += f[i][k]);
}
for(ll k=0; k<(1<<n); k++)
if(!vis[k]) f[i][k] = 0;
}
ll ans = 0;
for(ll i=0;i<=n;i++){
for(ll j=0; j<(1<<n); j++) addmod(w[i+1] += f[i][j]);
}
for(ll i=1;i<=n+1;i++){
ll xs = 1;
for(ll j=1; j<=n+1; j++) if(j!=i) xs = xs * qpow(i-j+mod, mod-2) % mod;
for(ll j=1; j<=n+1; j++) if(j!=i) xs = xs * (V-j+mod) % mod;
ans = (ans + xs * w[i]) % mod;
}
printf("%lld\n", ans);
}