题解:P14270 ABC253Ex 加强版
设
则
声明:以下指的集合幂级数运算均为无交并。
设
逐点牛顿迭代。
具体地,我们考虑先得出
首先显然
我们再搞一个新的集幂
这个复杂度是
现在考虑求出
能过
考虑
我们每次加入还没被
这样有什么好处呢?
首先不会算重,因为一种方案加入的顺序是唯一的。
然后我们还可以发现
我们考虑
这个过程你发现前
所以做一个大小为
也是
发现还有一个问题,就是很难钦定每次加入最小的连通块。
这是好办的,你按
你发现复杂度还是对的。
这部分的代码:
#include<bits/stdc++.h>
#define ppc(x) __builtin_popcount(x)
using namespace std;
namespace Fread {
const int SIZE=1<<21;char buf[SIZE],*S,*T;
inline char getchar() {if(S==T){T=(S=buf)+fread(buf,1,SIZE,stdin);if(S==T)return '\n';}return *S++;}
}
namespace Fwrite {
const int SIZE=1<<21;
char buf[SIZE],*S=buf,*T=buf+SIZE;
inline void flush(){fwrite(buf,1,S-buf,stdout);S=buf;}
inline void putchar(char c){*S++=c;if(S==T)flush();}
struct POPOSSIBLE{~POPOSSIBLE(){flush();}}ztr;
}
#define getchar Fread :: getchar
#define putchar Fwrite :: putchar
namespace Fastio{
struct Reader{
template<typename T>
Reader& operator >> (T& x) {
char c=getchar();T f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}x=0;
while(c>='0'&&c<='9'){x=x*10+(c-'0');c=getchar();}x*=f;
return *this;
}
Reader(){}
}cin;
struct Writer{
template<typename T>
Writer& operator << (T x) {
if(x==0){putchar('0');return *this;}
if(x<0){putchar('-');x=-x;}
static int sta[45];int top=0;
while(x){sta[++top]=x%10;x/=10;}
while(top){putchar(sta[top]+'0');--top;}
return *this;
}
Writer& operator << (char c) {putchar(c);return *this;}
Writer(){}
}cout;
}
#define cin Fastio :: cin
#define cout Fastio :: cout
const int N=31,Max=1048577,mod=998244353;
struct modint {
int val;
static int norm(const int& x) { return x < 0 ? x + mod : x; }
inline int Mod(int x){return x>=mod?x-mod:x;}
modint inv() const {
int a = val, b = mod, u = 1, v = 0, t;
while (b > 0) t = a / b, swap(a -= t * b, b), swap(u -= t * v, v);
return modint(u);
}
modint() : val(0) {}
modint(const int& m) : val(norm(m)) {}
modint(const long long& m) : val(norm(m % mod)) {}
modint operator-() const { return modint(norm(-val)); }
modint& operator+=(const modint& o) { return val = Mod(val + o.val), *this; }
modint& operator-=(const modint& o) { return val = norm(1ll * val - o.val), *this; }
modint& operator*=(const modint& o) { return val = static_cast<int>(1ll * val * o.val % mod), *this; }
modint operator-(const modint& o) const { return modint(*this) -= o; }
modint operator+(const modint& o) const { return modint(*this) += o; }
modint operator*(const modint& o) const { return modint(*this) *= o; }
friend std::ostream& operator<<(std::ostream& os, const modint& a) { return os << a.val; }
friend Fastio::Writer& operator<<(Fastio::Writer& os, const modint& a) { return os << a.val; }
}frac[N],inv[N],pw[Max],h[N];
int n,m,pre[Max],fg[N][N];
inline void init(int n=30){
frac[0]=inv[0]=1;for(int i=1;i<=n;++i) frac[i]=frac[i-1]*i;
inv[n]=frac[n].inv();for(int i=n-1;i;--i) inv[i]=inv[i+1]*(i+1);
}
inline modint Inv(int x){return frac[x-1]*inv[x];}
struct QAQ{QAQ(){init();}}QAQ;
struct poly{
vector<modint> p;modint& operator [](int x){return p[x];}
inline void init(int n){p.clear();p.resize(1<<n);}
inline void emplace(int n){p.resize(1<<n);}
inline int deg(){return p.size();}
inline void FMT(){int len=p.size(),n=__lg(len);for(int i=0;i<n;++i) for(int j=0;j<1<<n;++j) if((j>>i)&1) p[j]+=p[j^(1<<i)];}
inline void IFMT(){int len=p.size(),n=__lg(len);for(int i=0;i<n;++i) for(int j=0;j<1<<n;++j) if((j>>i)&1) p[j]-=p[j^(1<<i)];}
}x,f,g,y,dp[21];
inline int except(int S,int x){return ((S>>(x+1)<<x)|(S&((1<<x)-1)));}
inline void Mul(poly x,poly y,poly &z){//x*y->z
x.FMT();y.FMT();int len=x.deg();
z.p.resize(len);if(y.deg()!=len) exit(-1);
for(int i=0;i<len;++i) z[i]=x[i]*y[i];
z.IFMT();
}
poly ln(poly x){
static poly f[N],g[N];int n=__lg(x.deg());
for(int i=0;i<=n;++i){f[i].init(n);g[i].init(n);}
for(int i=0;i<(1<<n);++i) f[ppc(i)][i]=x[i];
for(int i=0;i<=n;++i) f[i].FMT();
for(int i=0;i<1<<n;++i){
g[0][i]=0;
for(int j=1;j<=n;++j){
for(int k=1;k<j;++k) g[j][i]-=f[k][i]*g[j-k][i]*(j-k);
g[j][i]=f[j][i]+g[j][i]*Inv(j);
}
}
for(int i=0;i<=n;++i) g[i].IFMT();
for(int i=0;i<1<<n;++i) x[i]=g[ppc(i)][i];
return x;
}
poly exp(poly x){
static poly f[N],g[N];int n=__lg(x.deg());
for(int i=0;i<=n;++i){f[i].init(n);g[i].init(n);}
for(int i=0;i<(1<<n);++i) f[ppc(i)][i]=x[i];
for(int i=0;i<=n;++i) f[i].FMT();
for(int i=0;i<(1<<n);++i){
g[0][i]=1;
for(int j=1;j<=n;++j){
for(int k=1;k<=j;++k) g[j][i]+=f[k][i]*k*g[j-k][i];
g[j][i]*=Inv(j);
}
}
for(int i=0;i<=n;++i) g[i].IFMT();
for(int i=0;i<1<<n;++i) x[i]=g[ppc(i)][i];
return x;
}
poly submul(poly x,poly &y){
static poly f[N],g[N],h[N];int n=__lg(x.deg());
for(int i=0;i<=n;++i){f[i].init(n);g[i].init(n);h[i].init(n);}
for(int i=0;i<(1<<n);++i) f[ppc(i)][i]=x[i];
for(int i=0;i<(1<<n);++i) g[ppc(i)][i]=y[i];
for(int i=0;i<=n;++i) f[i].FMT(),g[i].FMT();
for(int i=0;i<1<<n;++i){
for(int j=0;j<=n;++j){
for(int k=0;k<=j;++k) h[j][i]+=f[k][i]*g[j-k][i];
}
}
for(int i=0;i<=n;++i) h[i].IFMT();
for(int i=0;i<1<<n;++i) x[i]=h[ppc(i)][i];
return x;
}
inline poly Mul(poly &x,poly &y){poly z;Mul(x,y,z);return z;}
inline int E(int S,int T){return pre[S+T]-pre[S]-pre[T];}
inline int P(int i,int T){return E((1<<i),T);}
inline modint expow(modint x,int y){modint res=1;for(;y;y>>=1,x*=x) if(y&1) res*=x;return res;}
int main(){
cin>>n>>m;for(int i=1,x,y;i<=m;++i){cin>>x>>y;--x;--y;++pre[(1<<x)|(1<<y)];}
for(int i=0;i<n;++i) for(int j=0;j<(1<<n);++j) if((j>>i)&1) pre[j]+=pre[j^(1<<i)];
g.init(1);g[1]=1;
for(int i=1;i<n;++i){
f.init(i);g.emplace((i+1));
for(int j=0;j<(1<<i);++j) f[j]=g[j]*P(i,j);
f=exp(f);for(int j=0;j<(1<<i);++j) g[(1<<i)|j]=f[j];
}
dp[1]=g;h[1]=dp[1][(1<<n)-1];
for(int i=0;i<(1<<n);++i) if(!(i&1)) dp[1][i]=0;
for(int i=2;i<=n;++i) dp[i].init(n);
for(int i=1;i<n-1;++i){
for(int j=i;j<n;++j){
x.init(n-j);for(int k=0;k<(1<<(n-j));++k) if(!(k&1)) x[k]=dp[i][(k<<j)+(1<<j)-1];
y.init(n-j);for(int k=0;k<(1<<(n-j));++k) if((k&1)) y[k]=g[k<<j];
x=submul(x,y);for(int k=0;k<(1<<(n-j));++k) if((k&1)) dp[i+1][(k<<j)+(1<<j)-1]+=x[k];
}
h[i+1]=dp[i+1][(1<<n)-1];
}
for(int i=1;i<n;++i){
cout << frac[i]*h[n-i] << '\n';
}
return 0;
}