zoukankan      html  css  js  c++  java
  • 洛谷P1390 公约数的和 [2017年6月计划 数论12]

    P1390 公约数的和

    题目描述

    有一天,TIBBAR和LXL比赛谁先算出1~N这N个数中每任意两个不同的数的最大公约数的和。LXL还在敲一个复杂而冗长的程序,争取能在100s内出解。而TIBBAR则直接想1s秒过而获得完胜,请你帮他完成这个任务。

    输入输出格式

    输入格式:

    共一行,一个正整数N。

    输出格式:

    共一行,一个数,为1~N这N个数中每任意两个不同的数的最大公约数的和。

    输入输出样例

    输入样例#1:
    10
    输出样例#1:
    67

    说明

    对于40%的数据,2≤N≤2000.

    对于100%的数据,2≤N≤2000000.

    这个题怪好

    不妨设f(n) = (1,n) + (2,n) + (3,n) + (4,n) + ... + (n-2,n) + (n-1,n)

    则答案为f(2) + f(3) + f(4) + ... + f(n - 1) + f(n)

    对于任意数i,若(i, n) = k,  则(i/k, n/k) = 1,不难得到

    f(n) = Σ(i | n)phi(n/i) * i

    对于每个i,枚举其倍数n即可

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring> 
    #include <algorithm>
    #include <vector>
    #include <queue>
    inline void read(long long &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch >= '0' && ch <= '9')x = x * 10 + ch - '0', ch = getchar();}
    inline int max(int a, int b){return a > b ? a : b;}
    inline int min(int a, int b){return a < b ? a : b;}
    inline void swap(int &a, int &b){int tmp = a;a = b;b = tmp;}
    
    const int INF = 0x3f3f3f3f;
    const int MAXN = 2000000 + 10;
    
    long long n;
    long long ans;
    
    long long prime[MAXN],phi[MAXN],cnt;
    bool bp[MAXN];
    
    inline void makephi()
    {
        phi[1] = 1;
        for(register long long i = 2;i <= n;++ i)
        {
            if(!bp[i])
                prime[++cnt] = i, phi[i] = i - 1;
            
            for(register long long j = 1;j <= cnt;++ j)
            {
                if(i * prime[j] > n)break;
                bp[i* prime[j]] = 1;
                if(i % prime[j] == 0)
                {
                    phi[i * prime[j]] = phi[i] * prime[j];
                    break;
                }
                else
                    phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
        }
    }
    
    long long f[MAXN];
    
    int main()
    {
        read(n);
        makephi();
        for(register int i = 1;i <= n;i ++) 
        {
            for(register int j = i * 2;j <= n;j += i)
            {
                f[j] += phi[j / i] * i;
            }
        }
        for(register int i = 2;i <= n;++ i)
            ans += f[i];
        printf("%lld", ans);
        return 0;
    }
  • 相关阅读:
    EasyUI问题小结(不定期更新·······)
    windows服务与前台交互
    C#捕获Windows窗体控件
    C#操作AD域中计算机
    远程桌面 Rdp文件的生成
    正则匹配的例子
    Nodejs中npm install 命令的问题
    Windows下使用curl命令
    关于PostmanURL中不能传递中文的问题
    MyBatis_Study_004(动态代理)
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7096419.html
Copyright © 2011-2022 走看看