P2568 题解

思路

x=a×g,y=b×gx=a\times g,y=b\times g,其中 gg 为一个质数。根据 gcd\gcd 的性质我们可以知道,gcd(x,y)=g×gcd(a,b)\gcd(x,y)=g\times\gcd(a,b),而题目要求 gcd(x,y)\gcd(x,y) 也是质数,则说明 gcd(a,b)=1\gcd(a,b)=1,否则质数和一个大于 11 的数相乘后就不是个质数了。于是,这题就变成了对于所有质数 ddgcd(a,b)=1\gcd(a,b)=1 的个数,其中 a,bnda,b\le\lfloor\frac nd\rfloor(否则 a×d,b×da\times d,b\times d 就会超过 nn 了)。于是我们使用埃氏筛筛出欧拉函数,同时筛出所有质数,实现过程见代码,有注释。最后记得把欧拉函数前缀和,暴力求肯定 TLE 了。

代码

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
int t, n, m, prime[670005];
ll phi[10000005], sum;
int main () {
	ios::sync_with_stdio (0);
	cin.tie (0);
	cout.tie (0);
	cin >> n;
	for (int i = 1; i <= n; ++ i) //初始化,phi[i] 表示对于所有 1 <= j <= n,i 和 j 互质的个数
		phi[i] = i;
	for (int i = 2; i <= n; ++ i)
		if (phi[i] == i) { //没被筛过,说明是质数
			prime[++ m] = i; //放进质数表
			for (int j = i; j <= n; j += i) //注意只有 i 的倍数才会被筛掉
				phi[j] -= phi[j] / i; //剩下的数中有 1/i 会被 i 筛掉
		}
	for (int i = 2; i <= n; ++ i)
		phi[i] <<= 1, phi[i] += phi[i - 1]; //前缀和,乘 2 是因为这个数组是关于 y = x 轴对称的
	for (int i = 1; i <= m; ++ i)
		sum += phi[n / prime[i]];
	cout << sum;
	return 0;
}
posted @ 2024-05-07 16:55  Vitamin_B  阅读(24)  评论(0)    收藏  举报  来源