UVA11426

  链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=26&page=show_problem&problem=2421

  题意:求 n 以内的每两个数的最大公约数gcd(a, b)的和

  解题思路:假设m和n 是互质的两个数(m < n),那么gcd(m, n) = 1, 当题目中的 i, j 循环到m,n 时,g += 1,依此,当 i = k*m, j = k*n (k为整数),g += k 。

由此我们可以得出:结果 (g) 的变化是由互质的数变化引起的,所以我们的目的就是先求出 给定范围内的所有的互质的数,然后加上他们的倍数,最后求和即可。

  假设和 n 互质的数有 x 个,假设为x(k) (k <= x),那么在 i、j 循环到 x(k)、n 时结果会增加x,循环到(p*x(k), p*n) 时结果就会增加p*x。那么我们用table[i]记录各种x、n 在满足 x*n = i 时会增加多少结果,那么最后我们要输出的就是table[2] + table[3] + ... + table[N]。

  其中不得不提的是找 n 以内的与 n 互质的数(也就是求欧拉函数),然后求相应的table[x*n]。

  代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 
10 const int maxv = 4000002;
11 LL table[maxv];        //打表
12 int euler[maxv];    // 偶拉函数值
13 
14 void eul()
15 {
16     int i, j;
17     memset(table, 0, sizeof(table));
18     for(i = 1; i < maxv; ++i)    euler[i] = i;
19     for(i = 2; i < maxv; ++i)
20     {
21         if(euler[i] == i)    //对每个素数的倍数求欧拉函数表
22             for(j = i; j < maxv; j += i)
23                 euler[j] = euler[j] / i * (i-1);    //每遇到一个素数因子,就进行处理
24         for(j = 1; j*i < maxv; j++)
25             table[j*i] += j * euler[i];        //j倍
26     }
27     for(i = 1; i < maxv; ++i)
28         table[i] += table[i-1];        //n的值等于本身的值加上前面的值,因为是求和
29 }
30 
31 int main()
32 {
33     int n;
34     eul();
35     while(cin >> n && n)
36     {
37         cout << table[n] << endl;
38     }
39     return 0;
40 }

 

参考:http://www.cnblogs.com/staginner/category/320266.html

转载于:https://www.cnblogs.com/Duahanlang/p/3184994.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值