您的位置:首页 > 其它

UVA 11426 GCD - Extreme (II)(欧拉函数打表 + 规律)

2015-11-10 14:24 417 查看
Given the value of N, you will have to find the value of G. The definition of G is given below:
Here GCD(i, j) means the greatest common divisor of integer i and integer j.
For those who have trouble understanding summation notation, the meaning of G is given in the
following code:
G=0;
for(i=1;i<N;i++)
for(j=i+1;j<=N;j++)
{
G+=gcd(i,j);
}(i < j)
/*Here gcd() is a function that finds
the greatest common divisor of the two
input numbers*/
Input

The input file contains at most 100 lines of inputs. Each line contains an integer N (1 < N < 4000001).
The meaning of N is given in the problem statement. Input is terminated by a line containing a single
zero.

Output
For each line of input produce one line of output This line contains the value of G for the corresponding N.

The value of G will fit in a 64-bit signed integer.

Sample Input

10

100

200000

0

Sample Output

67

13015

143295493160

题目大意:就是求G

G
= gcd(1,2) + gcd(1,3) + ... + gcd(1,n-1) + gcd(1,n)
+gcd(2,3) + gcd(2,4) + ... + gcd(2,n-1) + gcd(2,n)
+...
+gcd(n-2,n)+ gcd(n-1,n);

这样我们可以得到一个规律:

G
= G[n - 1] + b
( 其中b
就是上面红色部分的和b
= gcd(1,n) + gcd(2,n) + ... + gcd(n-1,n) )

b
= gcd(1,n) + gcd(2,n) + ... + gcd(n-1,n)
b
的加数我们可以统另为gcd(b, n);

设a[xi] 表示使gcd(b,n) = xi成立的b的个数
那么b
= a[xi]*xi = a[x1]*x1 + a[x2]*x2 + a[x3]*x3 +...+a[xs]*xs
我们就要求a[xi]

gcd(b,n) = xi可以转化为求有多少个b/xi使gcd(b/xi,n/xi)=xi/xi = 1,要求b/xi的个数就相当于求与n/xi互质的数有多少个(即求n/xi的欧拉函数)因为只有互质的两个数气最大公约数才是1
那么我们最终求得就是b
= a[n/xi] *1 * xi (i = 1,2,3,...)

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>

using namespace std;

const int N = 4000010;
typedef long long ll;

ll a
, b
, G
;

int main()
{
ll n;
for(ll i = 0 ; i < N ; i++)
a[i] = i;//初始化
a[1] = 1;
for(ll i = 2 ; i < N ; i++)
{
if(a[i] == i)
{
a[i] -= a[i] / i;
for(ll j = i * 2 ; j < N ; j += i)
a[j] -= a[j] / i;
}
}//欧拉函数打表
for(ll i = 1 ; i < N ; i++)
{
for(ll j = i * 2 ; j < N ; j += i)
b[j] += a[j / i] * i;
}//b
打表(这里b的下标应含因子i)
G[2] = 1;
for(ll i = 3 ; i < N ; i++)
G[i] = G[i - 1] + b[i];//G
打表
while(scanf("%lld", &n), n)
{
printf("%lld\n", G
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: