51nod 1363 最小公倍数之和

来源:互联网 发布:开的淘宝店怎么找不到 编辑:程序博客网 时间:2024/06/06 03:47

51nod 1363

原题连接:
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1363

这个是一个不算很难的计算。

对于每次询问,给定n

answer=i=1nlcm(i,n)

=i=1ningcd(i,n)=ni=1nigcd(i,n)

则有:

answer=ni=1nigcd(i,n)=nk|n(1ki=1n[gcd(i,n)=k]i)=nk|n(i=1n[gcd(i,n)=k]ik)=nk|n(i=1n[gcd(i,n)=k]ik)

因为这个时候 iknk 互素

则:

answer=nk|n(i=1nk[ink]i)=nk|n(i=1k[ik]i)

记对于1n ,与 n 互素的 整数之和为S(n)

S(n)=i=1n[in]i

当 有 tn 时, 则必然有: (nt)n

所以,当n>1 时,每一个与n互素的整数 t 都 必然存在一个整数 u 有:

un    t+u=n

所以n>1时:

S(n)=ϕ(n)n2

n=1时:

S(n)=1

所以:

answer=nk|nS(k)=n(1+k|n ,k>1ϕ(k)k2)=n2(2+k|n ,k>1ϕ(k)k)=n2(1+k|nϕ(k)k)

积性函数的和函数依然是积性函数。

而积性函数的值可以由其 因式分解后的素数幂形式得来。

f(n)=ϕ(n)n 就是一个积性函数。

f(pk)=(pkp(k1))pk 其中,k>1.

那么其和函数素数幂形式是两个等比数列求和。

计算得:

F(pk)=k|pkf(k)=p(p2k1p21pp2k1p21)+1

(注:貌似暴力分解不会超时。也算是暴力题了)

#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;typedef long long LL;const LL mod=1e9+7;LL P(LL a,int b){    LL tmp=1;    while(b)    {        if(b&1)            tmp=tmp*a%mod;        a=a*a%mod;        b>>=1;    }    return tmp;}LL F(LL p,int k){    LL Iv=P((p*p%mod-1+mod)%mod,mod-2);    LL S=(P(p,k<<1)-1+mod)%mod;    S=S*Iv%mod;    S=p*(S*p%mod-S+mod)%mod;    return (S+1)%mod;}int main (){    int T;    LL Iv=P(2,mod-2);    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        LL N=(LL)n;        LL ans=1;        for(int i=2;i*i<=n;i++)        {            if(n%i) continue;            int k=0;            while(n%i==0)            {                k++;                n/=i;            }            ans*=F((LL)i,k);            ans%=mod;        }        if(n>1)            ans=(ans*F((LL)n,1))%mod;        printf("%lld\n",(((LL)1+ans)%mod)*N %mod * Iv % mod);    }    return 0;}
原创粉丝点击