Solution
设 fi f i 为点数为 i 时的答案, gi g i 为此时所有图个数,则 gi=2C2n g i = 2 C n 2
不难得到 fn=gn−∑n−1i=1fi∗gi∗Ci−1n−1 f n = g n − ∑ i = 1 n − 1 f i ∗ g i ∗ C n − 1 i − 1
把相关项处理一下就有
注意到只有一部分是未知的 利用多项式求逆把 fi f i 放到左边即可
其实还可以用CDQ分治解决 哪天写完了再放上来
Mistakes
才不是因为错误太多了单列一栏
- 指数对(Mo-1)取模 但指数的指数不能再运用费马小定理
- 多项式求逆中,次数界是变化的,所以要重新预处理
- 注意运算中每个多项式应保持次数界一致(补零)
- 时时检查运算溢出!
Code
#include <cstdio>
#include <cstring>
#include <iostream>
#define oo 2139062143
#define fo(i,x,y) for (ll i=(x);i<=(y);++i)
#define fd(i,x,y) for (ll i=(x);i>=(y);--i)
using namespace std;
typedef long long ll;
const ll N=8*(262144+10)/*2^18*/,mo=1004535809/*g=3*/;
ll n,M;
ll W[N],h[N],g[N],wz[N];
ll re[N],jc[N];
ll qsm(ll x,ll y)
{
y%=(mo-1);
ll rt=1;
fo(i,0,30)
{
if((1<<i)&y) rt=1ll*rt*x%mo;
x=1ll*x*x%mo;
}
return rt;
}
void init(ll x)
{
for(M=1;M<x;M<<=1);
W[0]=1,W[1]=qsm(3,(mo-1)/M);fo(i,2,M) W[i]=1ll*W[i-1]*W[1]%mo;
wz[0]=0;fo(i,1,M) wz[i]=(wz[i>>1]>>1)+((i&1)*(M>>1));
}
ll a[N];
void dft(ll *c)
{
fo(i,0,M-1) a[wz[i]]=c[i];ll tp;
for(ll wv=2,hf=1;wv<=M;hf=wv,wv<<=1)
fo(i,0,hf-1) for (ll l=i;l<M;l+=wv)
tp=1ll*W[1ll*M/wv*i]*a[l+hf]%mo,a[l+hf]=(a[l]-tp+mo)%mo,a[l]=(a[l]+tp)%mo;
fo(i,0,M-1) c[i]=(a[i]+mo)%mo;
}
ll d[N],e[N],f[N];
void opit(ll *c)//Rev[i]=2*rev[i]-a[i]*rev[i]*rev[i];
{
fo(i,0,M-1) d[i]=c[i],c[i]=0;
c[0]=qsm(d[0],mo-2);ll gg=M;
for (ll mp=2;mp<=gg;mp<<=1)
{
init(mp*2);
fo(i,0,M-1) e[i]=c[i];
dft(e);
fo(i,0,M-1) e[i]=(e[i]*e[i])%mo;
fo(i,0,(M>>1)-1)f[i]=d[i];fo(i,M>>1,M-1) f[i]=0;
dft(f);
fo(i,0,M-1) f[i]=(f[i]*e[i])%mo;
fo(i,1,M>>1) swap(W[i],W[M-i]);
dft(f);ll tp=qsm(M,mo-2);
fo(i,0,M-1) f[i]=f[i]*tp%mo;
fo(i,0,(M>>1)-1) c[i]=(2*c[i]-f[i]+mo)%mo;
}
}
ll C(ll x)
{
return((1ll*x*(x-1)/2));
}
int main()
{
scanf("%lld",&n);
jc[0]=1;fo(i,1,n) jc[i]=(1ll*jc[i-1]*i)%mo;
re[n]=qsm(jc[n],mo-2);
fd(i,n-1,0) re[i]=(1ll*re[i+1]*(i+1))%mo;
fo(i,0,n)
{
if(i)g[i]=1ll*qsm(2,C(i))*re[i-1]%mo;
h[i]=1ll*qsm(2,C(i))*re[i]%mo;
}
init(n*2);
dft(g);
opit(h);
init(n*2);
dft(h);
fo(i,0,M-1) h[i]=1ll*h[i]*g[i]%mo;
fo(i,1,M>>1) swap(W[i],W[M-i]);
dft(h);ll tp=qsm(M,mo-2);
ll p=(h[n]*tp)%mo;
printf("%lld",(1ll*p*jc[n-1]%mo));
return 0;
}