蒟蒻春赛 T2 30pts 求助
  • 板块学术版
  • 楼主zrt090604
  • 当前回复2
  • 已保存回复2
  • 发布时间2023/3/4 22:31
  • 上次更新2023/10/23 23:02:40
查看原帖
蒟蒻春赛 T2 30pts 求助
459188
zrt090604楼主2023/3/4 22:31

代码附有详细解释,求教大佬!

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, k, mn, ans, a[65], lim[65] = {0, 0, 1000000000, 1000000, 31622, 3981, 1000, 372, 177, 100, 63, 43, 31, 24, 19, 15, 13, 11, 10, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, range[65], num[65]; //lim[i]表示在a^i在long long范围内的最大取值a,防止溢出
int calc(int b, int p) { // 求[1,b]之间有多少个形如a^p的数
	int l = 0, r = 1e9;
	while(l <= r) {
		int mid = l+r >> 1;
		if(mid > lim[p]) {r = mid-1; continue;}
		int x = pow(mid, p);
		if(x > b) r = mid-1;
		else l = mid+1;
	}
	return r;
}
signed main () {
	scanf("%lld%lld", &n, &k);
	for(int i = 1;i <= 64;++i) num[i] = i;
	if(k == 1) printf("%lld", n), exit(0);
	int mx = log2(n);
	for(int i = 1;i < k;++i) num[i] = 0;
	for(int i = k;i <= 64;++i)
		for(int j = 2*i;j <= 64;j += i)
			num[j] = 0; 
	for(int i = 1;i <= 64;++i) 
		if(num[i]) a[i] = 1; // a数组表示需要筛查的次方数(a数组元素两两互质)
	for(int i = 2;i <= mx;++i) {
		if(!a[i]) continue;
		range[i] = calc(n, i); 
	}
	for(int i = k;i <= mx;++i) {
		if(a[i] == 0) continue;
		ans += range[i];
		for(int j = k;j < i;++j) {
			if(!a[j]) continue;
			ans -= calc(range[i], j) - 1; // 排除之前算过的数(例如4^3,在i=2时计算了一次,i=3时又算了一次,重复了。减1意思是把1去掉,因为1每一遍都有)
		}
		--ans; //去1
	}
	printf("%lld\n", ans+1); // 前面我们都把1排除在外了,最后应该给答案+1
	return 0;
}
2023/3/4 22:31
加载中...