题目链接:https://cn.vjudge.net/problem/UVA-11426
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); } /*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
题目翻译:
输入N,求下面代码执行之后,G的值。
输入
有多组数据,以0结尾。
每行一个整数N
输出
对于每个N,输出相应的结果G。
刘汝佳大白书(p125)的原题。
假设a、b(a<b)互质,那么gcd(a,b)=1,这样当i循环到a、j循环到b时就会向结果中+1,而i循环到2*a、j循环到2*b时就会向结果中+2(gcd(2*a,2*b)=2)...循环到k*a和k*b时就会向结果中+k。这样实际上引起结果变化的根源就在于各对互质的数,当i、j循环到他们自身或者自身的倍数时就会引起结果的改变,那么我们不妨先将每对互质的数对结果的贡献值算出来,最后将各对互质的数对结果的贡献累加起来就可以了。
假设和b互质的数有n个,也就是n对(?,b)(?和b互质),那么在i、j循环到?、b时结果会增加n,循环到(2*?,2*b)时结果就会增加2*n...当i、j循环到k*?、k*b时结果就会增加k*n。那么我们不妨用a[i]记录各种k、b在满足k*b=i时会增加多少结果,也就是说a[i]记录的是小于i的每个数与i最大公约数之和,那么最后我们要输出的就是a[2]+a[3]+...+a[N]。
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=4e6;
ll sum[maxn];
int phi[maxn];
void init(){
for(int i=1;i<=maxn;++i) phi[i]=i;
for(int i=2;i<=maxn;i++){
if(phi[i]==i)
for(int j=i;j<=maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
for(int j=1;j*i<=maxn;++j)
sum[j*i]+=j*phi[i];
}
for(int i=2;i<=maxn;++i)
sum[i]+=sum[i-1];
}
int main(){
ll n;
init();
while(~scanf("%lld",&n)&&n){
printf("%lld\n",sum[n]);
}
return 0;
}