• UVA GCD


    discription

    Given the value of N, you will have to find the value of G. The definition of G is given below:
    Here GCD(i, j) means the greatest common divisor of integer i and integer j.
    For those who have trouble understanding summation notation, the meaning of G is given in the
    following code:
    G=0;
    for(i=1;i<N;i++)
    for(j=i+1;j<=N;j++)
    {
    G+=gcd(i,j);
    }
    /*Here gcd() is a function that finds
    the greatest common divisor of the two
    input numbers*/
    Input
    The input file contains at most 100 lines of inputs. Each line contains an integer N (1 < N < 4000001).
    The meaning of N is given in the problem statement. Input is terminated by a line containing a single
    zero.
    Output
    For each line of input produce one line of output. This line contains the value of G for the corresponding
    N. The value of G will fit in a 64-bit signed integer.
    Sample Input
    10
    100
    200000
    0
    Sample Output
    67
    13015
    143295493160

    貌似是蓝书上有的一道题,当时刘汝佳是用 N log N 的筛法筛的,但是我们如果把积性函数推出来的话,可以

    把那个log也去掉,做到O(N)预处理,O(1)查询。

    大概最后就是推这么个积性函数: f(T)=Σφ(d)*(T/d)  ,其中d|T

    优化了一个log之后艹爆了时限hhh

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    #define maxn 4000005
    using namespace std;
    int zs[maxn/4],t=0,low[maxn+5];
    ll f[maxn+5],n,T;
    bool v[maxn+5];
    
    inline void init(){
        f[1]=1,low[1]=1;
        for(int i=2;i<=maxn;i++){
            if(!v[i]) zs[++t]=i,f[i]=i*2-1,low[i]=i;
            for(int j=1,u;j<=t&&(u=zs[j]*i)<=maxn;j++){
                v[u]=1;
                if(!(i%zs[j])){
                    low[u]=low[i]*zs[j];
                    if(low[i]==i) f[u]=f[i]*zs[j]+low[i]*(zs[j]-1);
                    else f[u]=f[i/low[i]]*f[low[u]];
                    break;
                }
                
                low[u]=zs[j];
                f[u]=f[i]*(2*zs[j]-1);
            }
        }
        
        for(int i=1;i<=maxn;i++) f[i]+=f[i-1];
    }
    
    int main(){
        init();
        while(scanf("%lld",&n)==1&&n) printf("%lld
    ",f[n]-n*(n+1)/2);    
        return 0;
    }
  • 相关阅读:
    docker常规操作——启动、停止、重启容器实例
    docker同时删除多个容器
    ubuntu中使用docker部署.netcore2.1
    .NET中RabbitMQ的使用
    Java开发环境Jave EE 和 jdk 下载
    WebApi用户登录验证及服务器端用户状态存取
    MVC中使用Ninject依赖注入
    起步:SpringBoot
    ML-对偶(Duality)问题 KKT 条件
    pandas 之 多层索引
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8319863.html
Copyright © 2020-2023  润新知