####题目链接:猛戳这里
####题目大意:
求
∑
i
=
1
n
l
c
m
(
i
,
n
)
\sum_{i=1}^{n}lcm(i,n)
∑i=1nlcm(i,n),比51nod上那道最小公倍数之和V2要简单。
####解题思路:
因为是上面那道题的简单版,所以可以直接套用上题的思路。又因为这道起点比较特殊又可以稍加变化速度也更快。
∑
i
=
1
n
l
c
m
(
i
,
n
)
=
∑
i
=
1
n
i
∗
n
g
c
d
(
i
,
n
)
=
n
×
∑
i
=
1
n
i
g
c
d
(
i
,
n
)
\sum_{i=1}^{n}lcm(i,n)=\sum_{i=1}^{n}\frac{i*n}{gcd(i,n)}=n\times\sum_{i=1}^{n}\frac{i}{gcd(i,n)}
i=1∑nlcm(i,n)=i=1∑ngcd(i,n)i∗n=n×i=1∑ngcd(i,n)i
到此两种方法的处理都相同。以后枚举每个因子,对每个因子所对应的和求的方法不同。
- n × ∑ d ∣ n n v × ( n v + 1 ) ÷ 2 × ∑ d ′ ∣ d μ ( d ′ ) × d ′ n\times\sum_{d\mid n}\frac{n}{v}\times(\frac{n}{v}+1)\div2\times\sum_{d'\mid d}\mu(d')\times d' n×d∣n∑vn×(vn+1)÷2×d′∣d∑μ(d′)×d′令 f ( d ) = ∑ d ′ ∣ d μ ( d ′ ) × d ′ f(d)=\sum_{d'\mid d}\mu(d')\times d' f(d)=∑d′∣dμ(d′)×d′, f ( d ) f(d) f(d)是积性函数, f ( p ) = 1 − p f(p)=1-p f(p)=1−p。具体过程参见上面链接
-
n
×
(
1
+
∑
d
∣
n
d
×
φ
(
d
)
/
2
)
n\times(1+\sum_{d\mid n}d\times\varphi(d)/2)
n×(1+d∣n∑d×φ(d)/2)
####代码:
莫比乌斯反演,复杂度 O ( T n ∗ 256 ∗ 8 ) O(T\sqrt n*256*8) O(Tn∗256∗8)
/* ********************************
Author : danmu
Created Time : 2016年07月12日 星期二 20时43分40秒
File Name : spoj5971.pp
******************************** */
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <list>
#include <map>
#include <set>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define _rep(i,x,y) for(int i=x;i>=y;--i)
#define CL(S,x) memset(S,x,sizeof(S))
#define CP (S1,S2) memcpy(S1,S2,sizeof(S2))
#define ALL(x,S) for(x=S.begin();x!=S.end();++x)
#define ULL unsigned long long
#define PI 3.1415926535
#define INF 0x3f3f3f3f
#define LL long long
const int maxn = 1005;
using namespace std;
int n;
int prime[maxn];
bool check[maxn];
int pri[50],pri_cnt;
int len[50];
vector<int> fac;
LL ans;
void mobius(){
memset(check,false,sizeof(check));
prime[0] = 0;
for(int i=2;i<maxn;++i){
if(!check[i]){
prime[++prime[0]] = i;
}
for(int j=1;j<=prime[0];++j){
if(i*prime[j] >= maxn) break;
check[i*prime[j]] = true;
if(i%prime[j] == 0) break;
}
}
}
void dfs(int res,int l){
if(l>=pri_cnt){
fac.push_back(res);
return;
}
dfs(res,l+1);
int tmp=1;
for(int i=1;i<=len[l];++i){
tmp*=pri[l];
dfs(res*tmp,l+1);
}
}
void getFac(){
pri_cnt=0;
int b_c=n;
for(int i=1;i<=prime[0]&&(LL)prime[i]*prime[i]<=b_c;++i){
if(b_c%prime[i]==0){
pri[pri_cnt]=prime[i];
len[pri_cnt]=0;
while(b_c%prime[i]==0){
b_c/=prime[i];
++len[pri_cnt];
}
++pri_cnt;
}
}
if(b_c>1){
pri[pri_cnt]=b_c;
len[pri_cnt++]=1;
}
fac.clear();
dfs(1,0);
}
void work(){
getFac();
ans=0;
for(int i=0;i<fac.size();++i){
int v=fac[i];
LL tmp=(LL)n/v*(n/v+1)/2;
LL res=1;
for(int j=0;j<pri_cnt;++j){
if(v % pri[j]) continue;
LL t = 1-pri[j];
res = res*t;
}
ans+=res*tmp;
}
ans*=n;
}
int main(){
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int t;
mobius();
scanf("%d",&t);
while(t--){
scanf("%d",&n);
work();
printf("%I64d\n",ans);
}
system("pause");
return 0;
}
复杂度 O ( T n ∗ 256 ) O(T\sqrt n*256) O(Tn∗256)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define LL long long
const int maxn=1000005;
int n;
LL ans=0;
bool ip[1010];
int prime[1010],cnt;
int phi[maxn];
int pri[10],len[10],pri_cnt;
void init(){
memset(ip,true,sizeof(ip));
ip[0]=ip[1]=false;
cnt=0;
for(int i=2;i<1010;++i){
if(ip[i]){
prime[cnt++]=i;
for(int j=i*i;j<1010;j+=i)
ip[j]=false;
}
}
for(int i=1;i<maxn;++i) phi[i]=i;
for(int i=2;i<maxn;i+=2) phi[i]/=2;
for(int i=3;i<maxn;i+=2)
if(phi[i]==i)
for(int j=i;j<maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
}
void getFac(){
int b_c=n;
pri_cnt=0;
for(int i=0;i<cnt&&(LL)prime[i]*prime[i]<=b_c;++i){
if(b_c%prime[i]==0){
pri[pri_cnt]=prime[i];
len[pri_cnt]=0;
while(b_c%prime[i]==0){
b_c/=prime[i];
++len[pri_cnt];
}
++pri_cnt;
}
}
if(b_c>1){
pri[pri_cnt]=b_c;
len[pri_cnt++]=1;
}
}
void dfs(int res,int l){
if(l>=pri_cnt){
ans+=(LL)res*phi[res]/2;
return ;
}
int tmp=1;
for(int i=0;i<=len[l];++i){
dfs(res*tmp,l+1);
tmp*=pri[l];
}
}
int main(){
int t;
init();
scanf("%d",&t);
while(t--){
ans=0;
scanf("%d",&n);
getFac();
dfs(1,0);;
printf("%I64d\n",(ans+1)*n);
}
system("pause");
return 0;
}
####总结:
- ∑ i = 1 n i g c d ( i , n ) = 1 + ∑ d ∣ n d × φ ( d ) / 2 = ∑ d ∣ n n v × ( n v + 1 ) ÷ 2 × ∑ d ′ ∣ d μ ( d ′ ) × d ′ \sum_{i=1}^{n}\frac{i}{gcd(i,n)}=1+\sum_{d\mid n}d\times\varphi(d)/2=\sum_{d\mid n}\frac{n}{v}\times(\frac{n}{v}+1)\div2\times\sum_{d'\mid d}\mu(d')\times d' ∑i=1ngcd(i,n)i=1+∑d∣nd×φ(d)/2=∑d∣nvn×(vn+1)÷2×∑d′∣dμ(d′)×d′
-
∑
i
=
1
n
n
g
c
d
(
i
,
n
)
=
∑
d
∣
n
d
×
φ
(
d
)
=
g
(
n
)
\sum_{i=1}^{n}\frac{n}{gcd(i,n)}=\sum_{d\mid n}d\times\varphi(d)=g(n)
∑i=1ngcd(i,n)n=∑d∣nd×φ(d)=g(n)
- 一百万以内的数最多有八个质因子,十亿以内的数最多有十二个。