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;
}
posted @ 2022-10-11 21:17  zyy2001  阅读(42)  评论(0编辑  收藏  举报