【未完善】GCD 极值(gcd) hgoi0501

GCD 极值(gcd) hgoi0501 题解


题目描述

题目描述


输入

  • 输入包括 T 组测试数据,每组数据只包含一个整数 N,含义如题所述。注意,测试数
    据中 T 的值未知。
    测试数据的最后一行是个 0,这一行无需处理。

输出

  • 每组测试数据输出一行,为 G 的值,其结果不会超过 64 位带符号整数。

样例

样例

数据规模

  • 对于 30% 的数据,2  N  1 000; 1  T  100
    对于 60% 的数据,2  N  4 000 000; 1  T  100
    对于另外的 40% 的数据,2  N  200 000; 1  T  20 000

题目解析

  • 一道非常玄妙的数学题。
  • 用到了欧拉函数的特性并使用递推和直接计算两种方法应对不同的数据规模。
  • 具体待补全

先附上AC程序

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
#define LIM 4000001
void finit(){
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);
}
ll g[LIM],flag[LIM],phi[LIM],sumphi[LIM];
ll prime[300000];
int prf=0;
int main(){
    finit();
    for (int i=2;i<=LIM;i++){
        if (!flag[i]) prime[prf++]=flag[i]=i;
        for (int j=0;j<prf&&i*prime[j]<=LIM;j++){
            flag[i*prime[j]]=prime[j];
            if (i%prime[j]==0)
                break;
        }
    }
    phi[1]=1;
    for (int i=2;i<LIM;i++){
        phi[i]=phi[i/flag[i]];
        if ((i/flag[i])%flag[i]==0)
            phi[i]*=flag[i];
        else
            phi[i]*=(flag[i]-1);
        sumphi[i]=sumphi[i-1]+phi[i];
    }
    ll n;
    ll maxx=1,sum=0;
    while (cin>>n){
        if (!n) break;
        if (n<=200000){
            if (n>maxx){
                for (int i=maxx+1;i<=n;i++){
                    g[i]=g[i-1]+phi[i];
                    for (int j=2;j<=sqrt(i);j++)
                        if (i%j==0)
                            if (i/j!=j)
                                g[i]+=phi[i/j]*j+phi[j]*(i/j);
                            else
                                g[i]+=phi[i/j]*j;
                }
                maxx=n;
            }
            cout<<g[n]<<'\n';
        }else{
            sum=sumphi[n];
            for(int i=2;i<=n/2;i++){
                sum+=sumphi[n/i]*i;
            }
            cout<<sum<<'\n';
        }
    }
    return 0;
}


发表评论

电子邮件地址不会被公开。 必填项已用*标注