Jeanny
寂兮,寥兮,独立不改,周行而不殆

[春季测试 2023] 幂次

题目描述

小 Ω 在小学数学课上学到了“幂次”的概念:\(\forall a, b \in \N^+\),定义 \(a^b\)\(b\)\(a\) 相乘。

她很好奇有多少正整数可以被表示为上述 \(a^b\) 的形式?由于所有正整数 \(m \in N^+\) 总是可以被表示为 \(m^1\) 的形式,因此她要求上述的表示中,必须有 \(b \geq k\),其中 \(k\) 是她事先选取好的一个正整数。

因此她想知道在 \(1\)\(n\) 中,有多少正整数 \(x\) 可以被表示为 \(x = a^b\) 的形式,其中 \(a, b\) 都是正整数,且 \(b \geq k\)

输入格式

第一行包含两个正整数 \(n, k\),意义如上所述。

输出格式

输出一行包含一个非负整数表示对应的答案。

样例 #1

样例输入 #1

99 1

样例输出 #1

99

样例 #2

样例输入 #2

99 3

样例输出 #2

7

样例 #3

样例输入 #3

99 2

样例输出 #3

12

提示

【样例 2 解释】

以下是全部 \(7\) 组符合题意的正整数及对应的一种合法的表示方法。

\(1 = 1^3, 8 = 2^3, 16 = 2^4, 27 = 3^3, 32 = 2^5, 64 = 4^3, 81 = 3^4\)

注意某些正整数可能有多种合法的表示方法,例如 \(64\) 还可以表示为 \(64 = 2^6\)

但根据题意,同一个数的不同的合法表示方法只会被计入一次。

【样例 3 解释】

以下是全部 \(12\) 组符合题意的正整数及对应的一种合法的表示方法。

\(1 = 1^2, 4 = 2^2, 8 = 2^3, 9 = 3^2, 16 = 4^2, 25 = 5^2, 27 = 3^3, 32 = 2^5, 36 = 6^2, 49 = 7^2, 64 = 8^2, 81 = 9^2\)

【样例 4】

见选手目录下的 power/power4.in 与 power/power4.ans。

【样例 5】

见选手目录下的 power/power5.in 与 power/power5.ans。

【样例 6】

见选手目录下的 power/power6.in 与 power/power6.ans。

【数据范围】

对于所有数据,保证 \(1 \leq n \leq 10^{18}\)\(1 \leq k \leq 100\)

测试点编号 \(n \le\) \(k\)
1 \(10^2\) \(=1\)
2 \(10^2\) \(\ge 2\)
3 \(10^4\) \(\ge 3\)
4 \(10^4\) \(\ge 2\)
5 \(10^6\) \(\ge 3\)
6 \(10^6\) \(\ge 2\)
7 \(10^8\) \(\ge 3\)
8 \(10^8\) \(\ge 2\)
9 \(10^{10}\) \(\ge 3\)
10 \(10^{10}\) \(\ge 2\)
11 \(10^{12}\) \(\ge 3\)
12 \(10^{12}\) \(\ge 2\)
13 \(10^{14}\) \(\ge 3\)
14 \(10^{14}\) \(\ge 2\)
15 \(10^{16}\) \(\ge 3\)
16 \(10^{16}\) \(\ge 2\)
17 \(10^{18}\) \(\ge 3\)
18 \(10^{18}\) \(\ge 2\)
19 \(10^{18}\) \(\ge 2\)
20 \(10^{18}\) \(\ge 2\)

题解:
算法复杂度:i*i<=\(10^{18}\), 枚举i是\(10^9\),可以枚举一下所有\(x^p\)的,85分。

#include<bits/stdc++.h>
using namespace std ;
long long n , k , ans=1 ;
bool vis[1000000005] ;
int main(){
	freopen("power.in" , "r" , stdin) ;
	freopen("power.out" , "w" , stdout) ;
	scanf("%lld%lld" , &n , &k) ;
	if(k==1){
		cout << n ;
		return 0 ;
	}
	for(int i=2 ; i*i<=n ; i++){
		if(vis[i]==1) continue ;
		bool flag = false ;
		int b=1 ;
		long long x = i ;
		while(n/x >= i){
			b++ ;
			x *= i ;
			if(x<=1000000000) vis[x] = 1 ;
			if(b>=k){
				ans++ ;
				flag = true ;
			}
		}
		if(flag==false) break ;
	}
	cout << ans ;
	
	return 0 ;
}

上述为yxm的代码。

进行优化:\(i*i*i<=10^{18}, 枚举i是10^6\),可以枚举一下所有\(x^p\)的,100分。
算一下所有p>=3的情况,去除p==2的情况,可以判断一下里面是完全平方数的数字。加上正好等于sqrt(l)
当k>3的时候,可以用下面的方法实现:

			s*=i; K++;
			if(mp[s]) continue; mp[s] = 1;
			if(K >= k) cnt++;
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5;
map<ll, bool> mp; 
ll zt, tot, cnt,k,r;
void init(ll n){
	for(ll i=2;i*i*i<=n;i++){//1e6
		ll s=i*i; ll K = 2;
		while(s<=n/i){
			s*=i; K++;
			if(mp[s]) continue; mp[s] = 1;
			if(K >= k) cnt++;
			ll sq = sqrtl(s); 
			if(sq * sq == s && sq <= (ll)sqrtl(n)) zt++;
			tot++;
		}
	}
}
int main(){	
	cin>>r>>k;
	init(r);
	if(k == 1) cout<<r<<endl;
	else if(k == 3) cout<<tot+1<<endl;
	else if(k == 2) cout<<(ll)sqrtl(r)+tot-zt<<endl;
	else cout<<cnt+1<<endl;
	return 0;
}
posted on 2023-03-25 18:46  Jeanny  阅读(44)  评论(0)    收藏  举报