H - GCD - Extreme (II)(欧拉函数)

数论(欧拉函数的应用)

写题解之前先说一下:这种解法不是看别人的题解写出来的是真的强(也可能是我太菜了吧)
题目链接
然后这是我参考的大佬的题解的链接
大佬的题解
在这里插入图片描述题意:就是求题目中那个程序,只不过要化简一下,不然绝对会超时
题解:化简程序后可以得到其中有一部分是f(n)=gcd(1,n)+gcd(2,n)+…+gcd(n-1,n);还有几部分是f(n-1)=gcd(1,n-1)+gcd(2,n-2)+…+gcd(n-2,n-1);以此类推:可以得到f(n-2),f(n-3)…f(2);
为什么没有f(1)呢?f(1)=f(0,1)???所以题目就变成了求s(n)=f(2)+f(3)+…f(n)(有没有f(1)我就不清楚了,欢迎留言告诉我)很明显这要求前缀和很简单,但是f(n)怎么求呢?(像这种求gcd而且还要求那么多的,可以往欧拉函数想)gcd(x,n)=i;那么gcd(x/i,n/i)=1;就代表x/i与n/i互质,那么phi(n/i)代表小于n/i并且与n/i互质的个数(欧拉函数求解)。(这里面n%i==0,i是n的因数)则phi(n/i)个数的和为phi(n/i)i,因为phi(n/i)是gcd(x,n)=i的个数。那么f(n)=sum(iphi(n/i))i是n的因数;(写着写着自己都懵逼了,没看懂的话就去看一下上面那个大佬的题解吧,我太菜了)

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 4e6+ 50;
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
const ll  lnf  = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
const  double pi=3.141592653589;
int phi[maxn];
//一个一个求欧拉函数太慢了,直接上欧拉表
void find_phi()
{
    for(int i=0;i<maxn;i++)
    {
        phi[i]=i;
    }
    for(ll i=2;i<maxn;i++)
    {
        if(phi[i]==i)
        {
            for(ll j=i;j<maxn;j+=i)
            {
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}
ll ans[maxn];
int main()
{

    ll n;
    find_phi();
    for(int i=1;i<maxn;i++)
    {
        for(int j=i*2;j<maxn;j+=i)
        {
            ans[j]+=phi[j/i]*i;
        }
    }
    for(int i=1;i<maxn;i++)
    {
        ans[i]+=ans[i-1];
    }
    while(~scanf("%lld",&n))
    {
       printf("%lld\n",ans[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qcccc_/article/details/107331170