P7728 旧神归来(Return of Them)
P7728 旧神归来(Return of Them)
设\(Q_x(x)\)为原树操作\(x\)次后中各深度叶子节点数量的\(\tt OGF\),\(G_x(x)\)为原树操作\(x次\)中各深度节点数量的\(OGF\),默认\(Q/G=Q_0/G_0,\)T为操作\(\infty\)后的树(通天树
设操作\(\infty\)次过程中,各深度叶子操作次数,所以有:
\[Q_\infty=\sum_{i=0}^\infty Q_0^i=\frac{1}{1-Q_0}
\]
原理是将树的深度为\(i\)的叶子替换成原树后,每个新树中的叶子深度变成了\(i+j\)
想象初始时从虚无之中诞生了原始,则\(T\)必能映照与始源或衍生之中,本质无异于前叶引之链长似卷,故可借母函得以阐释:\(G_\infty=Q_\infty G_0\)
换吾之视听,以深\(i\)操数为\(a_i\),次覆次以为,得:\(G_0\prod_{i=1}^\infty(1+x^i)^{a_i}\equiv D \equiv G_0Q_\infty\pmod {x^m}\)
\(x^m\nmid G_0\Rightarrow \prod_{i=1}^\infty(1+x^i)^{a_i} \equiv Q_\infty\pmod {x^m}\)
此下均以等代模
夫积者,难为之解,若为则难免于\(\tt T\)之悲
思以对化此积为和者,故得:\(\sum_{i=1}^\infty a_i\ln(1+x^i)=-\ln(1-Q)\)
此处略引:
\[\begin{aligned}
\int d\ln(1+x^i)&=\int\frac{d\ln(1+x^i)}{d(1+x^i)}d(1+x^i)\\
&=\int\frac{1}{1+x^i}dx^i\\
\end{aligned}
\]
有\(\frac{1}{1+x}=\sum_{j=0}^\infty (-1)^{j}x^j\)
故:
\[\begin{aligned}
\int d\ln(1+x^i)&=\int\frac{1}{1+x^i}dx^i\\
&=\int \sum_{j=0}^\infty (-1)^j(x^i)^jdx^i\\
&=\sum_{j=0}^\infty\frac{(-1)^j(x^i)^{j+1}}{j+1}\\
&=\sum_{j=1}^\infty\frac{(-1)^jx^{ij}}{j}
\end{aligned}
\]
回原点,有:
\[\sum_{i=1}^\infty\sum_{j=1}^\infty\frac{a_i(-1)^jx^{ij}}{j}=-\ln(1-Q)\\
\Rightarrow \sum_{i|n}\frac{a_i(-1)^{n\over i}i}{n}=[x^n]-\ln(1-Q)
\]
线性递推,多项式求\(\tt ln\)即可,时间复杂度\(O(n\log n)\)
#include<bits/stdc++.h>
using namespace std;
# define read read1<int>()
# define Type template<typename T>
Type inline T read1(){
T n=0;
char k;
bool fl=0;
do (k=getchar())=='-'&&(fl=1);while('9'<k||k<'0');
while(47<k&&k<58)n=(n<<3)+(n<<1)+(k^48),k=getchar();
return fl?-n:n;
}
# define f(i,l,r) for(int i=(l);i<=(r);++i)
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define ll long long
class Array{
private:
vector<int>a;
public:
Array(const int size,const int f):a(size,f){}
void push(int n){a.push_back(n);}
Array(int* l=NULL,int* r=NULL){while(l!=r)push(*l),++l;}
inline int size(){return a.size();}
inline int& operator [] (const int x){return a[x];}
void resize(int n){a.resize(n);}
void clear(){a.clear();}
void swap(){reverse(a.begin(),a.end());}
int& top(){return a[a.size()-1];}
void pop(){a.pop_back();}
};
const int mod=998244353,g=3,inv2=499122177;
Array operator -(Array a,Array b){
int N=a.size(),M=b.size();
Array t;
for(int i=0;i<N||i<M;++i){
t.push((i<N?a[i]:0)-(i<M?b[i]:0));
t.top()%=mod;
if(t.top()<0)t.top()+=mod;
}
return t;
}
Array operator +(Array a,Array b){
int N=a.size(),M=b.size();
Array t;
for(int i=0;i<N||i<M;++i){
t.push((i<N?a[i]:0)+(i<M?b[i]:0));
if(t.top()>=mod)t.top()-=mod;
}
return t;
}
Array operator *(Array a,int n){
int N=a.size();
for(int i=0;i<N;a[i]=(ll)a[i]*n%mod,++i);
return a;
}
Array operator *(int n,Array a){return a*n;}
int qkpow(int b,int m,int mod){
int tem=b,ans=1;
for(;m;m>>=1,tem=(ll)tem*tem%mod)
if(m&1)ans=(ll)ans*tem%mod;
return ans;
}
int* NTT(const int len,Array& a,const bool Ty,int* r=NULL){
if(!r){
r=new int[len];
r[0]=0;int L=log2(len);
f(i,0,len-1)
r[i]=(r[i>>1]>>1)|((i&1)<<L-1);
}
f(i,0,len-1)
if(i<r[i])swap(a[i],a[r[i]]);
for(int i=1;i<len;i<<=1){
int T=qkpow(Ty?g:332748118,(mod-1)/(i<<1),mod);
for(int W=i<<1,j=0;j<len;j+=W){
ll omega=1;
for(int k=0;k<i;++k,omega=omega*T%mod){
ll x(a[j+k]),y(omega*a[i+j+k]%mod);
a[j+k]=x+y;(a[j+k]>mod)&&(a[j+k]-=mod);
a[i+j+k]=x-y+mod;(a[i+j+k]>mod)&&(a[i+j+k]-=mod);
}
}
}
return r;
}
Array operator * (Array x,Array y){
int n=x.size()-1,m=y.size()-1;
int limit=1;
while(limit<=n+m)limit<<=1;
Array ans;
x.resize(limit+1);
y.resize(limit+1);
int *r;
r=NTT(limit,x,1);
NTT(limit,y,1,r);
f(i,0,limit)x[i]=(ll)x[i]*y[i]%mod;
NTT(limit,x,0,r);
int tem=qkpow(limit,mod-2,mod);
f(i,0,n+m)ans.push((ll)x[i]*tem%mod);
return ans;
}
Array& operator *= (Array& x,Array y){
return x=x*y;
}
void Rev(Array &x,Array y){
int n=x.size()-1,m=y.size()-1;
int limit=1;
while(limit<=n+m)limit<<=1;
Array ans;
x.resize(limit+1);
y.resize(limit+1);
int *r;
r=NTT(limit,x,1);
NTT(limit,y,1,r);
f(i,0,limit)x[i]=(ll)(2ll-(ll)x[i]*y[i]%mod+mod)%mod*y[i]%mod;
NTT(limit,x,0,r);
int tem=qkpow(limit,mod-2,mod);
f(i,0,n+m)x[i]=(ll)x[i]*tem%mod;
x.resize(n+m+1);
}
Array Inv(Array a){
int N=a.size();
if(N==1)return Array(1,qkpow(a[0],mod-2,mod));
Array b=a;b.resize(N+1>>1);
b=Inv(b);b.resize(N);
Rev(a,b);
a.resize(N);
return a;
}
Array operator / (Array x,Array y){
int N=x.size()-1,M=y.size()-1;
if(N<M)return Array(1,0);
x.swap();y.swap();
y.resize(N-M+1);
x*=Inv(y);
x.resize(N-M+1);
x.swap();
return x;
}Array operator % (Array x,Array y){
x=x-x/y*y;
int n=x.size();
Array t;
while(n&&!x[n-1])--n;
for(int i=0;i<n;++i)t.push(x[i]);
return t;
}
Array sqrt(Array x){
int N=x.size();
if(N==1)return Array(1,1);
Array y=x;
y.resize(N+1>>1);
y=sqrt(y);
y.resize(N);
Array z=Inv(y);
return inv2*(y+x*z);
}
Array diff(Array x){
for(int i=0;i+1<x.size();++i)
x[i]=(ll)x[i+1]*(i+1)%mod;
x.pop();
return x;
}
Array integral(Array x){
for(int i=x.size();--i;)
x[i]=(ll)x[i-1]*qkpow(i,mod-2,mod)%mod;
x[0]=0;
return x;
}
Array ln(Array x){
int N=x.size();
x=integral(diff(x)*Inv(x));
x.resize(N);
return x;
}
Array exp(Array x){
int N=x.size();
if(N==1)return Array(1,1);
Array y=x;
y.resize(N+1>>1);
y=exp(y);
y.resize(N);
y[0]=1;
y*=(x+Array(1,1)-ln(y));
y.resize(N);
return y;
}
Array x;
int s,m,h=-1;
ll inv[100005],a[100005];
vector<int>G[100005];
void dfs(int n,int fa){
bool vis=0;++h;
for(auto i:G[n])
if(i!=fa){
dfs(i,n);
vis=1;
}if(!vis)--x[h];--h;
}
int main(){
s=read;m=read;
int w=max(s,m)+1;
x.resize(w+5);
inv[1]=1;
for(int i=2;i<=w;++i)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for(int i=1;i<s;++i){
int u=read,v=read;
G[u].push_back(v);
G[v].push_back(u);
}dfs(1,0);
x[0]=1;
x=ln(x);
for(int i=1;i<w;++i){
a[i]=(a[i]-x[i])%mod;
for(int j=2;i*j<=w;++j)
if(j&1)a[i*j]=(a[i*j]-a[i]*inv[j])%mod;
else a[i*j]=(a[i*j]+a[i]*inv[j])%mod;
}
ll t=0;
for(int i=1;i<=m;++i)printf("%lld\n",(t=t+a[i]+mod)%=mod);
return 0;
}
因果乃旋转纺车,光彩之多面明镜
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存