列表

详情


NC206572. HelloGCD

描述

o_o最近学习了一个数论知识:gcd,gcd(a,b)表示整数a和b的最大公约数。
o_o发现了很多有趣的结论,他现在要你求 f(n) 的值,你能告诉他吗?


由于答案可能很大,你需要输出 后的值。

输入描述

第一行输入一个整数 ,表示有T组样例。
第二含输入一个整数

输出描述

对于每组样例输出一行,表示 后的值。

示例1

输入:

2
1
3

输出:

1
19

示例2

输入:

3
2
20
2020

输出:

7
2684
81327884

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 13ms, 内存消耗: 4744K, 提交时间: 2020-09-09 09:14:29

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7,N=5e5+5;
ll n;
vector<ll>v;
ll ans[N];
ll tot,p[N],phi[N];
void init()
{
    phi[1]=1;
    for(ll i=2;i<N;i++)
    {
        if(!phi[i]) phi[i]=i-1,p[++tot]=i;
        for(ll j=1;j<=tot&&i*p[j]<N;j++)
        {
            if(i%p[j]==0)
            {
                phi[i*p[j]]=phi[i]*p[j];
                break;
            }
            phi[i*p[j]]=phi[i]*phi[p[j]];
        }
    }
}
map<ll,ll>mp;
ll Phi(ll x)
{
    if(x<N) return phi[x];
    if(mp[x]) return mp[x];
    ll ans=x,y=x;
    for(ll i=2;i*i<=x;i++)
        if(x%i==0)
        {
            ans-=ans/i;
            while(x%i==0) x/=i;
        }
    if(x>1) ans-=ans/x;
    return mp[y]=ans;
}
ll sol(ll n,ll d)
{
    assert(n%d==0);
    return 1ll*Phi(d)*(n/d)%mod;
}
ll solve(ll d)
{
    ll ans=0;
    ans=0;
    for(ll x:v)
        if(d%x==0)
        ans=(ans+sol(n/x,d/x)*(n/(d/x)))%mod;
    return ans;
}
int main()
{
    init();
    ll t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        v.clear();
        for(ll i=1;i*i<=n;i++)
            if(n%i==0)
        {
            v.push_back(i);
            if(i!=n/i) v.push_back(n/i);
        }
        sort(v.begin(),v.end());
        ll res=0;
        for(ll i=v.size()-1;i>=0;i--)
        {
            ans[i]=solve(v[i]);
            for(ll j=i+1;j<v.size();j++)
                if(v[j]%v[i]==0)
                 ans[i]=(ans[i]-ans[j])%mod;
            res=(res+ans[i]*v[i])%mod;
        }
        res=(res+mod)%mod;
        printf("%lld\n",res);
    }
}

上一题