Gym102471Cディリクレk番目のルート

リンク
次のデフォルトの関数です\(F(1)= 1 \)
まず補題を与える:\(F = P ^ \イプシロン\)
補助定理の使用が容易に証明することができ(F = G ^ K \ 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