码迷,mamicode.com
首页 > 其他好文 > 详细

【LGP4714】「数学」约数个数和

时间:2019-06-18 14:19:57      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:can   约数个数   www   sig   分配   algorithm   https   return   std   

题目

众所周知,除数个数函数\(\sigma_0=I^2\)\(I\)就是狄利克雷卷积里的\(1\)函数

于是熟悉狄利克雷卷积的话很快就能看出我们要求的就是\(I\times I^{k}\),即\(I^{k+1}\),我们给这个函数起一个名字叫\(f^{k+1}\)

显然这个东西是积性函数,于是我们考虑一下指数次幂的\(f\)如何求

显然

\[f^{k+1}(n)=\sum_{d|n}f^{k}(d)\]

对于指数次幂\(p^m\)

\[f^{k+1}(p^m)=\sum_{i=0}^mf^k(p^i)\]

我们考虑一下快速求\(f^{k+1}(p^m)\),发现就是就是把这\(m\)次幂分配到\(k+1\)次减少的机会里去,当然最后不一定减少到\(0\),于是等价于把\(m\)个球分给\(k+2\)个盒子,允许为空,插板一下得知这个是\(\binom{k+m+1}{m+1}\),我们发现这个组合数非常好算,于是直接暴力就好了,由于又是积性函数,我们分解质因数之后直接合并就可以了

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define min std::min
#define LL long long
const int maxn=1e7+5;
const int mod=998244353;
int f[maxn],p[maxn>>2],inv[505];
LL n,m;int T,ans=1;
inline int C(LL n,int m) {
    int now=1;
    for(re int i=n;i>=n-m+1;--i) now=1ll*now*(i%mod)%mod;
    for(re int i=1;i<=m;i++) now=1ll*now*inv[i]%mod;
    return now;
}
int main() {
    scanf("%lld%lld",&n,&m);inv[1]=1;
    for(re int i=2; i<505; i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    f[1]=1;T=std::sqrt(n)+1;T=min(T,maxn-1);
    for(re int i=2;i<=T;i++) {
        if(!f[i]) p[++p[0]]=i;
        for(re int j=1;j<=p[0]&&p[j]*i<=T;j++) {
            f[p[j]*i]=1;
            if(i%p[j]==0) break;
        }
    }
    p[++p[0]]=1e9+7,p[++p[0]]=998244353,p[++p[0]]=1e9+9;
    for(re int i=1;i<=p[0];i++) {
        int t=0;
        while(n%p[i]==0) n/=p[i],t++;
        if(!t) continue;
        ans=1ll*ans*C((t+m+1)%mod,t)%mod;
    }
    if(n!=1) ans=1ll*ans*C(m+2,1)%mod;
    printf("%d\n",ans);
    return 0;
}

【LGP4714】「数学」约数个数和

标签:can   约数个数   www   sig   分配   algorithm   https   return   std   

原文地址:https://www.cnblogs.com/asuldb/p/11044730.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!