HDU 2582 f(n)
This time I need you to calculate the f(n) . (3<=n<=1000000)
f(n)= Gcd(3)+Gcd(4)+…+Gcd(i)+…+Gcd(n).
Gcd(n)=gcd(C[n][1],C[n][2],……,C[n][n-1])
C[n][k] means the number of way to choose k things from n some things.
gcd(a,b) means the greatest common divisor of a and b.
Input
There are several test case. For each test case:One integer n(3<=n<=1000000). The end of the in put file is EOF.
Output
For each test case:
The output consists of one line with one integer f(n).
Sample Input
3
26983
Sample Output
3
37556486
题意:
给出公式
Gcd(n)=gcd(C[n][1],C[n][2],……,C[n][n−1])
G
c
d
(
n
)
=
g
c
d
(
C
[
n
]
[
1
]
,
C
[
n
]
[
2
]
,
…
…
,
C
[
n
]
[
n
−
1
]
)
,
让求
f(n)=Gcd(3)+Gcd(4)+…+Gcd(i)+…+Gcd(n)
f
(
n
)
=
G
c
d
(
3
)
+
G
c
d
(
4
)
+
…
+
G
c
d
(
i
)
+
…
+
G
c
d
(
n
)
。
分析:
对于 G=gcd(C1n,C2n,C3n...Cn−1n) G = g c d ( C n 1 , C n 2 , C n 3 . . . C n n − 1 ) 来说
有且仅有以下三种情况:
(1) 如果n为素数, G=n G = n
(2) 如果n有两个或两个以上的素因子, G=1 G = 1
(3) 如果n只有一个素因子 p p ,
为什么会这样呢
下面一一进行分析:
例子:n = 5
51 5×42×1 5×4×33×2×1 5×4×3×24×3×2×1
5
1
5
×
4
2
×
1
5
×
4
×
3
3
×
2
×
1
5
×
4
×
3
×
2
4
×
3
×
2
×
1
我们首先把组合数按照分数形式写出来(不约分化简)会发现,最大公因数必须是和分子上的n相关的,即n的因子(包括它本身),其最大公因数最大为n,为什么?
因为观察分子处n之外的其他数在每个组合数中是逐渐增加的,即第一个只有n这个数本身,第二个相比前一个多乘了一个n-1,第三个相比前一个多乘了n-2,这样最大公因数必须是共有的,所以一定不能在这些数里面找,所以必定是n或n的因数,因此下面的分析我们只对n进行考虑就可以了
明白了上面的分析
这个问题分析的关键便是分母对于分子上n的影响了
(1) 如果n为素数,
G=n
G
=
n
:
举个例子,拿5来说我们要求
51 5×42×1 5×4×33×2×1 5×4×3×24×3×2×1 5 1 5 × 4 2 × 1 5 × 4 × 3 3 × 2 × 1 5 × 4 × 3 × 2 4 × 3 × 2 × 1
的最大公因数
组合数的分母实际上会最终便利
[1,n−1]
[
1
,
n
−
1
]
,但是由于n是素数,所以找不到一个因子会使得n变化,也就是说分子上的n经过约分化简后仍然是n,这样最大公因数一定是n。
正如举得例子,因为5是素数,所以分母1,2,3,4都不能约分5,最终5不会变,因此最大公因数是5
(2) 如果n有两个或两个以上的素因子, G=1 G = 1 :
举个例子拿6来说
因为6含有2个质因子2和3,因为组合数的分母会遍历完1-5,也就一定会遍历到2和3
61 6×52×1 6×5×43×2×1 6×5×4×34×3×2×1 6×5×4×3×25×4×3×2×1 6 1 6 × 5 2 × 1 6 × 5 × 4 3 × 2 × 1 6 × 5 × 4 × 3 4 × 3 × 2 × 1 6 × 5 × 4 × 3 × 2 5 × 4 × 3 × 2 × 1
这样一定存在一个组合数,分母有2,使得6消去了2剩下了3,也一定存在一个组合数,分母有3,使得6消去了3只剩下2,因为这两个组合数的存在,6约分后剩下的两个素因子是互质的,这样这两个组合数的最大公因数一定为1,从而导致所有6的组合数的最大公因子都是1
(3) 如果n只有一个素因子
p
p
,:
首先明确含有一个素因子的话说明一定是素数幂的形式即
pk
p
k
因为如果不是要么是第一种情况,他就是素数,要么是第二种情况还有别的素因子(算术基本定理任何数可以分解成素数的乘积)
假设
n=pk
n
=
p
k
分母在便利1到n-1的过程中,一定会有一个组合数的分母含有一个
p,p2,...pk−1
p
,
p
2
,
.
.
.
p
k
−
1
这就会使得分子上的n经过约分后变成了
pk,pk−1,pk−2,...p
p
k
,
p
k
−
1
,
p
k
−
2
,
.
.
.
p
这样他们的最大公因数必然是p
举个例子拿4来说
41 4×32×1 4×3×23×2×1
4
1
4
×
3
2
×
1
4
×
3
×
2
3
×
2
×
1
因此,对于一个所给的数n,我们先判断一下是否是素数,是素数直接加本身,不是素数进行质因子分解,超过两个质因子就加1,只有一个质因子就加这个质因子,分别利用筛素数+质因子分解+打表
然后O(1)输出答案
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
ll prime[maxn];
bool isprime[maxn];
int cnt;
void init(){
memset(isprime,true,sizeof(isprime));
for(int i = 2; i < maxn; i++){
if(isprime[i]){
prime[cnt++] = i;
for(int j = i+i; j < maxn; j += i){
isprime[j] = false;
}
}
}
}
ll resolve(int n){
int k;
int num = 0;
for(int i = 0; i < cnt && prime[i] * prime[i] <= n; i++){
if(n % prime[i] == 0){
num++;
if(num > 1) return 1;
k = prime[i];
while(n % prime[i] == 0) n /= prime[i];
}
}
if(num == 1 && n == 1) return k;
if(num == 0 && n > 1) return n;
return 1;
}
ll f[maxn];
void get(){
init();
f[2] = 0;
for(int i = 3; i < maxn; i++){
if(isprime[i]) f[i] = f[i-1] + i;
else f[i] = f[i-1] + resolve(i);
}
}
int main(){
get();
int n;
while(~scanf("%d",&n)){
printf("%lld\n",f[n]);
}
return 0;
}