51nod 1363
原题连接:
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1363
这个是一个不算很难的计算。
对于每次询问,给定
n
:
answer=∑i=1nlcm(i,n)
=∑i=1ningcd(i,n)=n∑i=1nigcd(i,n)
则有:
answer=n∑i=1nigcd(i,n)=n∑k|n(1k∑i=1n[gcd(i,n)=k]∗i)=n∑k|n(∑i=1n[gcd(i,n)=k]∗ik)=n∑k|n(∑i=1n[gcd(i,n)=k]∗ik)
因为这个时候 ik 与 nk 互素
则:
answer=n∑k|n(∑i=1nk[i⊥nk]∗i)=n∑k|n(∑i=1k[i⊥k]∗i)
记对于
1
到 n ,与
n
互素的 整数之和为S(n) :
S(n)=∑i=1n[i⊥n]∗i
当 有 t⊥n 时, 则必然有: (n−t)⊥n
所以,当
n>1
时,每一个与
n
互素的整数 t 都 必然存在一个整数
u
有:
u⊥n 且 t+u=n
所以 n>1 时:
S(n)=ϕ(n)n2
n=1 时:
S(n)=1
所以:
answer=n∑k|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)=(pk−p(k−1))∗pk 其中,k>1.
那么其和函数素数幂形式是两个等比数列求和。
计算得:
F(pk)=∑k|pkf(k)=p(p2k−1p2−1p−p2k−1p2−1)+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;
}