Loading

春测2023 T2题解

这是一个从暴力到正解的过程。

暴力#

1 枚举到 n,枚举每一个 x,进行累乘,顺便用一个map数组判重,时间复杂度O(nlognlogn),直接T飞。

改善1#

此时我们抛开复杂度的 lognlogn 不谈,发现当枚举的 i 大于 n13 小于等于 n 时,只能够算它的二次方,没有必要枚举。

故如果 k=2,我们在枚举时,如果当前指数为 b,则当 b 为双数时(因为就是 (ab2)2,同样也是某数的方),故意不加答案,等最后令答案加上 n 就行,这样复杂度降至 O(n13lognlogn)

改善2#

试着不用map数组判重,可以发现,重复时会有 ab=cd ,而这种情况会有 xe=a,xf=c。这样,ab=cd=xn,在枚举 x 时这加上就行。所以在枚举的时候,将自己筛到的打上标记。当 ab106 时,vis[ab]=1

如果 x 为非整数呢?则 ac 也是非整数(指数得是整数),所以不必担心。

这样在枚举底数时,如果自己已经被 vis 标记,直接下一个,既不会有重复,又优化了复杂度。复杂度 O(n13logn),可过此题。

上代码#

#include<bits/stdc++.h>
#define int __int128
using namespace std;
bool vis[2000000];

int ll=0; 
inline __int128 read(){
    __int128 x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void print(__int128 x){
    if(x<0){putchar('-');x=-x;}
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
signed main(){
//	freopen("power.in","r",stdin);
//	freopen("power.out","w",stdout);
	long long n,k;
	cin>>n>>k;
	if(k==1){
		print(n);return 0;
	}
	if(k>log2(n)){
		cout<<1;return 0;
	}
	int ans=1;
	int b=0;
	for(int a=2;a<=1000000;a++){
		int res=a;b=1;
		if(vis[res])continue;
		while(1){
			b++;
			res=res*a;
			if(b>=k&&res<=n){
				if(k==2&&res<=n&&b%2==0){//只有k=2时才不加 
					if(res<=1000000)vis[res]=1;//标记 
					continue;//不加答案 
				}
				ans++;
			}
			if(res<=1000000)vis[res]=1;//注意不管符不符合答案就会标记上 
			if(res>=n)break;
		}
	}
	if(k==2)ans+=(int)sqrtl(n)-1;//因为ans初值为1,表示1也符合答案,所以在这里sqrtl(n)也包含了1,需减去 
	print(ans);
	return 0;
}

作者:lalaouye

出处:https://www.cnblogs.com/lalaouyehome/p/17190007.html

版权:本作品采用「114514」许可协议进行许可。

posted @   lalaouye  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示