51Nod 1769 Clarke and math2

51Nod 1769 Clarke and math2


http://www.51nod.com/Challenge/Problem.html#!#problemId=1769

要算的是\(G=F*I^k\),考虑怎么求\(I^k\)

\(I^k(n=\prod_{i=1}^mp_i^{e_i})=\prod_{i=1}^mC_{e_i+k-1}^{e_i}\)

\(C_{e_i+k-1}^{e_i}\)显然可以直接求。

直接线性筛\(I^k\),然后卷\(F\)

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 1000000007
typedef long long ll;
il ll gi(){
    ll x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))f^=ch=='-',ch=getchar();
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f?x:-x;
}
il int pow(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=1ll*ret*x%mod;
        x=1ll*x*x%mod;y>>=1;
    }
    return ret;
}
int f[500010];
char K[1000010];
int pr[500010],Ik[500010],p,_Ik[500010],d[500010],ans[500010];
bool yes[500010];
int Ck[30];
int main(){
#ifdef XZZSB
    freopen("in.in","r",stdin);
    freopen("out.out","w",stdout);
#endif
    int n=gi(),k=0;scanf("%s",K+1);
    int lenk=strlen(K+1);
    for(int i=1;i<=lenk;++i)k=(k*10ll+K[i]-'0')%mod;
    for(int i=1;i<=n;++i)f[i]=gi();
    Ck[0]=1;
    for(int i=1;i<30;++i){
        Ck[i]=1;
        for(int j=1;j<=i;++j)Ck[i]=1ll*Ck[i]*j%mod;
        Ck[i]=pow(Ck[i],mod-2);
        for(int j=1;j<=i;++j)Ck[i]=1ll*Ck[i]*(i+k-j)%mod;
    }
    Ik[1]=1;
    for(int i=2;i<=n;++i){
        if(!yes[i])pr[++p]=i,Ik[i]=Ck[1],_Ik[i]=1,d[i]=1;
        for(int j=1;j<=p&&i*pr[j]<=n;++j){
            yes[i*pr[j]]=1;
            if(i%pr[j]==0){
                Ik[i*pr[j]]=1ll*_Ik[i]*Ck[d[i]+1]%mod;
                _Ik[i*pr[j]]=_Ik[i];
                d[i*pr[j]]=d[i]+1;
                break;
            }
            Ik[i*pr[j]]=1ll*Ik[i]*Ck[1]%mod;
            _Ik[i*pr[j]]=Ik[i];
            d[i*pr[j]]=1;
        }
    }
    for(int i=1;i<=n;++i)
        for(int j=i;j<=n;j+=i)
            ans[j]=(ans[j]+1ll*Ik[i]*f[j/i])%mod;
    for(int i=1;i<=n;++i)printf("%d ",ans[i]);
    return 0;
}

转载于:https://www.cnblogs.com/xzz_233/p/11142049.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值