傳送門
題解:
我記得 SCOI2019 考完之後我就口胡過這個東西,當時D1T3 超矩形。。。
考慮 Dirichlet 生成函數:。
考慮 Dirichlet 卷積:,不難發現 Dirichlet 卷積的 Dirichlet 生成函數就是原 Dirichlet 生成函數的卷積。
所以我們現在只需要考慮生成函數的開根和求冪即可,支持一下 和 就行了,我們只需要明白 怎麼做, 直接就是 的逆運算。
按照套路 ,求逆沒什麼好講的,直接搞就行了,求導會發現這個玩意 :
這個 有點難搞,不過我們知道外層有個求不定積分最後會把 搞掉,我們需要維護的只有比值,就是說我們需要構造函數 ,使其滿足 。定義 爲 的所有質因子指數之和即可。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
char obuf[(int)(1e7+7)],*oh=obuf,ch[23];
template<typename T>void print(T a,char c){
if(a<0)*oh++='-',a=-a;int tl=0;
do ch[++tl]=a%10;while(a/=10);
while(tl)*oh++=ch[tl--]^48;*oh++=c;
}struct obuf_flusher{~obuf_flusher(){fwrite(obuf,1,oh-obuf,stdout);}}Flusher;
}using IO::gi;
using IO::print;
using std::cerr;
using std::cout;
cs int mod=998244353;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod,a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int po(int a,int b){int r=1;for(;b;b>>=1,Mul(a,a))if(b&1)Mul(r,a);return r;}
inline void ex_gcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return;}ex_gcd(b,a%b,y,x);y-=a/b*x;
}inline int Inv(int a){static int x,y;ex_gcd(mod,a,y,x);return x+(x>>31&mod);}
cs int N=1e6+7;
int p[N],pc;
bool mrk[N];
int c[N];
void sieves(int n){
for(int re i=2;i<=n;++i){
if(!mrk[i])p[++pc]=i,c[i]=1;
for(int re j=1;i*p[j]<=n;++j){
mrk[i*p[j]]=true;
c[i*p[j]]=c[i]+1;
if(i%p[j]==0)break;
}
}
}
int inv[100];
void Ln(int *f,int *t,int n){
for(int re i=1;i<=n;++i)
t[i]=mul(f[i],c[i]);
for(int re i=1;i<=n;++i)if(t[i])
for(int re j=2;i*j<=n;++j)
Dec(t[i*j],mul(f[j],t[i]));
for(int re i=1;i<=n;++i)
Mul(t[i],inv[c[i]]);
}
void Exp(int *f,int *t,int n){
for(int re i=1;i<=n;++i)
t[i]=i==1,Mul(f[i],c[i]);
for(int re i=1;i<=n;++i)if(t[i]){
Mul(t[i],inv[c[i]]);
for(int re j=2;i*j<=n;++j)
Inc(t[i*j],mul(t[i],f[j]));
}
}
void Root(int *f,int n,int k){
static int g[N];
Ln(f,g,n);k=Inv(k);
for(int re i=1;i<=n;++i)
Mul(g[i],k);
Exp(g,f,n);
}
int n,k;
int f[N];
void Main(){
n=gi(),k=gi();inv[0]=inv[1]=1;
for(int re i=2;i<100;++i)
inv[i]=mul(inv[mod%i],mod-mod/i);
for(int re i=1;i<=n;++i)f[i]=gi();
sieves(n);Root(f,n,k);
for(int re i=1;i<=n;++i)
print(f[i],' ');
}
inline void file(){
#ifdef zxyoi
freopen("dirichlet.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}