codeforces 1036 F. Relatively Prime Powers (容斥+精度处理+大数边界处理)

题目链接:https://codeforces.com/contest/1036/problem/F

如果分解后的质因子个数的 (gcd) 不为 (1),那原数是 (n) 开方,枚举开方数按莫比乌斯函数容斥,注意 (pow) 函数的精度问题,可以先调高上界然后向下调整精度

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 105;

int T;
ll n;

int cnt;
int prime[1010], mu[1010], is_prime[1010];

ll qsm(ll i, ll po){
	ll res = 1ll;
	while(po){
		if(po & 1) { // 防止乘爆
			if(res >= 2e18/i) return 2e18+7;
			res = res * i;
		}
		
		if(po > 1){
			if(i >= 2e18/i) return 2e18+7;
			i = i * i;
		}
		po >>= 1;
	}
	return res;
}

int calc(int x){
	int l = max(1, (int)pow(n, 1.0/x)-3), r = (int)pow(n, 1.0/x)+3;
	int res = 0;
	while(l <= r){
		int mid = (l + r) / 2;
		if(qsm(mid, x) <= n){
			res = mid;
			l = mid + 1;
		} else{
			r = mid - 1;
		}
	}
	return res - 1;
}

int main(){
	mu[1] = 1;
	for(int i = 2; i <= 100; ++i){
		if(!is_prime[i]){
			prime[++cnt] = i;
			mu[i] = -1;
		}
		for(int j = 1 ; j <= cnt && prime[j] * i <= 100 ; ++j){
			is_prime[i * prime[j]] = 1;
			if(i % prime[j] == 0) {
				mu[i * prime[j]] = 0;
				break;
			} else {
				mu[i * prime[j]] = -mu[i];
			}
		}
	}
	
	scanf("%d", &T);
	while(T--){
		scanf("%lld", &n);
		ll ans = n-1;
		for(int i = 2 ; (1ll<<i) <= n ; ++i){
			if(mu[i] == 0) continue;
			ans += 1ll * mu[i] * calc(i);
		}
		printf("%lld
", ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/15253978.html