221. 龙哥的问题
题目链接
221. 龙哥的问题
龙哥现在有一道题,要考考大家。
给定一个整数 \(N\),请你求出 \(\sum_{1 \le i \le N} gcd(i,N)\)的值。
输入格式
一个整数 \(N\)。
输出格式
一个整数表示结果。
数据范围
\(1 < N < 2^{31}\)
输入样例:
6
输出样例:
15
解题思路
欧拉函数
设 \(gcd(i,n)=d\),则有 \(gcd(i/d,n/d)=1\),原问题即转化为有多少个这样的 \(i\),其贡献都为 \(d\),显然满足 \(gcd(i/d,n/d)\) 的 \(i\) 有 \(\phi(n/d)\) 个,答案即为 \(\sum_{d|n}d\times \phi(n/d)=\sum_{d|n}n/d\times \phi(d)\),这时直接暴力可过,但是还可以继续优化,$\sum_{d|n}n/d\times \phi(d)=n\times \sum_{d|n}(1-1/p_{1d})\times (1-1/p_{2d})\times \dots \times (1-p_{kd}) \(,同时,\) n=p_1^{\alpha_1}\times p_2^{\alpha_2}\times \dots \times p_t^{\alpha_t}$,继续对 \(d\) 进行分析:\(d\) 为 \((1 +p_1+p_1^2+\dots +p_1^{\alpha_1})\times (1 +p_2+p_2^2+\dots +p_2^{\alpha_2})\times \dots\times (1 +p_t+p_t^2+\dots +p_t^{\alpha_t})\) 展开后的任意一项,而任意一个 \(d\) 都对应一个 \(\prod (1-1/p_{id})\),故 \(n\times \sum_{d|n}(1-1/p_{1d})\times (1-1/p_{2d})\times \dots \times (1-p_{kd})=n\times (1+(1-1/p_1)+(1-1/p_1)+\dots +(1-1/p_1))\times (1+(1-1/p_2)+(1-1/p_2)+\dots +(1-1/p_2))\times \dots \times (1+(1-1/p_t)+(1-1/p_t)+\dots +(1-1/p_t))=n\times (1+\alpha_1\times (1-1/p_1))\times (1+\alpha_2\times (1-1/p_2))\times \dots \times (1+\alpha_t\times (1-1/p_t))\)
- 时间复杂度:\(O(\sqrt{n})\)
代码
// Problem: 龙哥的问题
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/223/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int n;
int main()
{
cin>>n;
LL res=n;
for(int i=2;i<=n/i;i++)
if(n%i==0)
{
int s=0;
while(n%i==0)s++,n/=i;
res/=i,res*=(LL)i+s*i-s;
}
if(n>1)res/=n,res*=(LL)n+n-1;
cout<<res<<'\n';
return 0;
}
- 暴力
// Problem: 龙哥的问题
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/223/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int n;
int phi(int x)
{
int res=x;
for(int i=2;i<=x/i;i++)
if(x%i==0)
{
res/=i;
res*=(i-1);
while(x%i==0)x/=i;
}
if(x>1)res/=x,res*=(x-1);
return res;
}
int main()
{
cin>>n;
LL res=0;
for(int i=1;i<=n/i;i++)
{
if(n%i==0)
{
res+=i*phi(n/i);
if(i!=n/i)res+=n/i*phi(i);
}
}
cout<<res<<'\n';
return 0;
}