Gym102471C Dirichlet k-th root

Link
下面的函数都默认\(f(1)=1\)
先给出一个引理:\(f^p=\epsilon\)
利用引理可以很方便地证明\(f^k=g\Leftrightarrow f=g^{\frac1k}\)
但是这个引理我不会证。
还有一个做法是倍增递推,可以上网找到。

#include<cstdio>
#include<cctype>
#include<cstring>
const int N=100007,P=998244353;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
    void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put(' ');}
}using namespace IO;
int f[N],g[N],n,k;
void mod(int&x){x+=x>>31&P;}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
void conv(int*a,const int*b)
{
    static int c[N];memset(c+1,0,n<<2);
    for(int i=1;i<=n;++i) for(int j=1;i*j<=n;++j) mod(c[i*j]+=mul(a[i],b[j])-P);
    memcpy(a+1,c+1,n<<2);
}
 
int main()
{
    n=read(),k=read();
    for(int i=1;i<=n;++i) g[i]=read();
    for(f[1]=1,k=pow(k,P-2);k;k>>=1,conv(g,g))if(k&1)conv(f,g);
    for(int i=1;i<=n;++i) write(f[i]);
    Flush();
}

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/12234481.html