zoukankan      html  css  js  c++  java
  • 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
Copyright © 2011-2022 走看看