zoukankan      html  css  js  c++  java
  • pku 2480 Longge's problem 最大公约数的和

    做法:
    直接求过不了
    只能考虑  对于gcd(M,N)=i 有Ci个M满足此式 答案便是∑(Ci*i)
    gcd(M,N)=i  <=> gcd(M/i,N/i)=1
    而求gcd(M/i,N/i)=1 有多少个M/i满足 这便是欧拉函数Phi()的定义
    所以就转化为了求Phi(N/i)

    枚举每个 M|N  求出Phi(N/i)  答案便是 ∑(Phi(N/i)*i)
    那么如何枚举每个  M|N 呢?
    很简单 枚举1到sqrt(N)的所有整数,所有的约数便是 j|N (N/j)|N
    这样就搞定了
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const int nmax = 50005;
    int prime[nmax], flag[nmax];
    int plen;
    void mkprime() {
    int i, j;
    memset(flag, -1, sizeof(flag));
    for (i = 2; i < nmax; i++) {
    if (flag[i]) {
    for (j = i + i; j < nmax; j += i)
    flag[j] = 0;
    }
    }
    for (i = 2, plen = 0; i < nmax; i++)
    if (flag[i])
    prime[plen++] = i;
    }
    int getPhi(int n) {
    int i, te, phi;
    te = (int) sqrt(n * 1.0);
    for (i = 0, phi = n; (i < plen) && (prime[i] <= te); i++) {
    if (n % prime[i] == 0) {
    phi = phi / prime[i] * (prime[i] - 1);
    while (n % prime[i] == 0) {
    n /= prime[i];
    }
    }
    }
    if (n > 1) {
    phi = phi / n * (n - 1);
    }
    return phi;
    }

    void solve(int n) {
    int i, j, te;
    LL sum;
    te = static_cast<int>(sqrt(1.0 * n));
    for (i = 1, sum = 0; i <= te; i++) {
    if (n % i == 0) {
    j = n / i;
    sum += i * getPhi(j);
    if (i != j) {
    sum += j * getPhi(i);
    }
    }
    }
    printf("%I64d\n", sum);
    }
    int main() {
    #ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
    #endif
    int n;
    mkprime();
    while (~scanf("%d", &n)) {
    solve(n);
    }
    return 0;
    }

     
     
    [分析]:

    设f(n)=∑gcd(i,n)

    推论1:1~n与n的最大公约数为p的个数等于φ(n div p)

    所以可以得出f(n)=∑φ(n div p)*p (p|n)    

    设 n=(p1^k1)(p2^k2)....(pn^kn)   (p1,p2..pn ∈ Prime)

    所以有: f(n)=f(p1^k1)f(p2^k2)....f(pn^kn)

    所以我们只需求出求f(pi^ki)即可

    f(p^k)=∑[( p^c )φ( p^(k-c) )] (0<=c<=k)   由于∑k比较小,我们可以枚举c

    对于φ( p^i)(p ∈ Prime)有 φ( p^i)=(p-1)p^(i-1) 但有φ(1)=1

     

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #define LL long long
    #define nmax 46345
    int prime[nmax], plen;
    void mkprime() {
    int i, j;
    memset(prime, -1, sizeof(prime));
    for (i = 2; i < nmax; i++) {
    if (prime[i]) {
    for (j = i + i; j < nmax; j += i) {
    prime[j] = 0;
    }
    }
    }
    for (i = 2, plen = 0; i < nmax; i++) {
    if (prime[i]) {
    prime[plen++] = i;
    }
    }
    }
    int getPow(int a, int b) {
    int res;
    res = 1;
    while (b) {
    if (b & 1) {
    res = res * a;
    }
    b >>= 1;
    a = a * a;
    }
    return res;
    }
    int getpPhi(int p, int c) {
    if (c == 0) {
    return 1;
    }
    return (p - 1) * getPow(p, c - 1);
    }
    LL cal(int p, int c) {
    int i;
    LL sum, temp;
    for (i = 0, sum = 0, temp = 1; i <= c; i++) {
    sum += temp * getpPhi(p, c - i);
    temp *= p;
    }
    return sum;
    }
    void solve(int n) {
    int i, te, cnt;
    LL res;
    te = (int) (sqrt(n * 1.0));
    for (i = 0, res = 1; (i < plen) && (prime[i] <= te); i++) {
    if (n % prime[i] == 0) {
    cnt = 0;
    while (n % prime[i] == 0) {
    cnt++;
    n /= prime[i];
    }
    res = res * cal(prime[i], cnt);
    }
    }
    if (n > 1) {
    res = res * cal(n, 1);
    }
    printf("%I64d\n", res);

    }

    int main() {
    #ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
    #endif
    int n;
    mkprime();
    while (scanf("%d", &n) != EOF) {
    solve(n);
    }
    return 0;
    }


  • 相关阅读:
    WEB前端第四十四课——jQuery框架(二)常用方法
    WEB前端第四十三课——jQuery框架(一)$()函数、添加事件监听
    WEB前端第四十二课——应用案例-瀑布流、递归、代理
    WEB前端第四十一课——简单算法与解析indexof、hash、冒泡排序、递归、JSON
    WEB前端第四十课——正则表达式-RegExp、高级
    WEB前端第三十九课——HTML正则表达式-基础、修饰符、检索模式
    SITE STRUCTURE
    CSS GRID ESSENTIALS
    CSS TYPOGRAPHY
    CSS COLOR
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/2119499.html
Copyright © 2011-2022 走看看