Longge(欧拉函数)
题目描述:求 $ \displaystyle \sum_{i=0}^N gcd(i,N)$ ,\(N \le 2^{32}\).
大数据,优化.
从 \(1\) 到 \(n\) 所有数只有两种情况,和 \(n\) 有共同的因子或者没有(好像是废话),
如果有的话,这个共同的因子一定是 \(n\) 的因子(好像又是废话)。
(考虑一种特殊的情况,一个数与 \(n\) 的公因数恰好是 \(n\) 的质因子,那么这个数一定满足是这个质因子的倍数,
且与其他质因子互素。)
那对于任意一个数 \(i\) 呢,如果他是 \(n\) 的因数,那么如果倍数 \(k\) 与 \(n/i\) ———也就是\(n\) 的其他因子互质时,
\(i×k\) 与 \(n\) 的最大公因数就是 \(i\),由此我们可以通过找 \(n\) 的因子来统计这个因子被加了多少次。
找 \(k\) 时可以用 \(\varphi\) 找乘积不大于 \(n\) 的倍数。
再优化一下,只需要找 \(1-- \sqrt n\) 就可以,注意判 \(\sqrt n\).
#include<bits/stdc++.h>
using namespace std;
long long n;
long long exgcd(long long k)
{
long long m=(long long)sqrt(k);
long long ans=k;
for(long long i=2;i<=m;i++)
{
if(k%i==0)
{
ans=ans/i*(i-1);
while(k%i==0) k/=i;
}
}
if(k>1) ans=ans/k*(k-1);
return ans;
}
int main()
{
scanf("%lld",&n); long long cnt=0;
long long m=(long long)sqrt(n);
for(long long i=1;i<=m;i++)
{
if(n%i==0&&i!=n/i) cnt+=i*exgcd(n/i)+(n/i)*exgcd(i);
else if(n%i==0&&i==n/i) cnt+=i*exgcd(n/i);
}
printf("%lld",cnt);
return 0;
}