zoukankan      html  css  js  c++  java
  • 【 欧拉函数 】GCD

    • Step1 Problem

    原题 给一个数n,输出sigma(gcd(i,j))1<=i<=j,i<=j<=n

    • Step2 Ideas:

    假设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]。

        至于找和b互质的数,就是计算b的欧拉函数的值,然后暴力循环k,并修改对应的a[k*b]即可,整体的复杂度是O(N*logN)的。

        欧拉公式的延伸小于n 与n互质的数的和 是euler(n)*n/2

    思路来源

    • Step3 Code:
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<bitset>
     6 #include<cassert>
     7 #include<cctype>
     8 #include<math.h>
     9 #include<cstdlib>
    10 #include<ctime>
    11 #include<deque>
    12 #include<iomanip>
    13 #include<list>
    14 #include<map>
    15 #include<queue>
    16 #include<set>
    17 #include<stack>
    18 #include<vector>
    19 #define lt k<<1
    20 #define rt k<<1|1
    21 #define lowbit(x) x&(-x)
    22 #define lson l,mid,lt
    23 #define rson mid+1,r,rt
    24 using namespace std;
    25 typedef long long  ll;
    26 typedef long double ld;
    27 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    28 #define mem(a, b) memset(a, b, sizeof(a))
    29 //#define int ll
    30 const double pi = acos(-1.0);
    31 const double eps = 1e-6;
    32 const double C = 0.57721566490153286060651209;
    33 const ll mod = 3e7;
    34 const int inf = 0x3f3f3f3f;
    35 const ll INF = 0x3f3f3f3f3f3f3f3f;
    36 const int maxn = 4e6 + 5;
    37 int phi[maxn];
    38 ll a[maxn];
    39 
    40 void prep() {
    41     mem(a, 0);
    42     for(int i = 1; i <= 4e6; i++) phi[i] = i;
    43     for(int i = 2; i <= 4e6; i++) {
    44         if(phi[i] == i) {
    45             for(int j = i; j <= 4e6; j += i) {
    46                 phi[j] = phi[j] / i * (i - 1);
    47             }
    48         }
    49         for(int j = 1; j * i <= 4e6; j++) a[j * i] += j * phi[i];
    50     }
    51     for(int i = 1; i <= 4e6; i++) a[i] += a[i - 1];
    52 }
    53 
    54 int main() {
    55     prep();
    56     int n;
    57     while(cin >> n && n) {
    58         cout << a[n] << endl;
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    linux 短信收发
    sama5d3 环境检测 adc测试
    【Codeforces 723C】Polycarp at the Radio 贪心
    【Codeforces 723B】Text Document Analysis 模拟
    【USACO 2.2】Preface Numbering (找规律)
    【Codeforces 722C】Destroying Array (数据结构、set)
    【USACO 2.1】Hamming Codes
    【USACO 2.1】Healthy Holsteins
    【USACO 2.1】Sorting A Three-Valued Sequence
    【USACO 2.1】Ordered Fractions
  • 原文地址:https://www.cnblogs.com/zyysyang/p/11347278.html
Copyright © 2011-2022 走看看