首页 > 其他 > 详细

HDU-5628 Clarke and math-狄利克雷卷积+快速幂

时间:2019-09-27 18:06:16      阅读:90      评论:0      收藏:0      [点我收藏+]

技术分享图片

 

 解法:我们观察这个g(i)的式子。我们设h(i)=1发现:

当k=1,g=sigma(i1|i) f(i1) = sigma(i1|i) f(i1) * h(i/i1) =Dirchlet ( h* f )

当k=2,g=sigma(i2|i1) f(i2) = Dirchlet( h * Dirchlet(h * f ) )

......

当k=k,g= Dirchlet( h * Dirchlet( h * Dirchlet(h * f) ) )  里面有k个括号

其实就是  g=h * h *h ...* f  (*代表狄利克雷卷积)

学过狄利克雷卷积应该知道是满足结合律的,那么我们就用快速幂计算 h^k ,最后再做一次卷积就能得到结果。

注意要储存h^k的数组g必须g[1]=1才能存下来。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
const int MOD=1e9+7;
int n,k;
LL f[N],g[N],h[N];

LL c[N];
void Dirch(LL *a,LL *b) {  //计算a=a*b的狄利克雷卷积 
    memset(c,0,sizeof(c));
    for (int i=1;i<=n;i++)
        for (int j=i;j<=n;j+=i)
            c[j]=(c[j]+a[i]*b[j/i]%MOD)%MOD;
    memcpy(a,c,sizeof(c));        
}

int main()
{
    int T; cin>>T;
    while (T--) {
        scanf("%d%d",&n,&k);
        for (int i=1;i<=n;i++) scanf("%d",&f[i]);
        for (int i=1;i<=n;i++) h[i]=0,g[i]=1;
        h[1]=1;
        for (;k;k>>=1) {
            if (k&1) Dirch(h,g);
            Dirch(g,g);
        }
        Dirch(f,h);
        for (int i=1;i<=n;i++) printf("%lld%c",f[i],i==n ? \n :  );
    }
    return 0;
}

 

HDU-5628 Clarke and math-狄利克雷卷积+快速幂

原文:https://www.cnblogs.com/clno1/p/11599344.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!