[PA2011] Prime prime power

分析

注意到本题用到了常用的一个套路:对 \(b\) 是否大于 \(2\) 分类讨论。

因为 \(b>2\) 也就是 \(b\ge3\)\(a\le10^6\),所以考虑把 \(3\times10^6\)(因为有 \(k\) 的存在)前的质数筛出来,暴力找到 \(a^b\) 加入统计答案的 set(\(2^{60}>10^{18}\),因此 \(b\le59\))。

接下来考虑 \(b=2\) 的时候,由于 \(a^2\) 增长迅速,所以不需要枚举很多的 \(a\)。从 \(\lceil\sqrt{n}\rceil\) 开始枚举约 \(1000\) 个数的时候就可以了。

最后先把 set 中小于等于 \(n\) 的数 erase 掉,然后再 erase 掉前 \(k-1\) 个元素,再输出 set 中头元素的值就可以了。注意经常判断一下当前的数是否超过 \(10^18\)

AC Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
set<int> st;
bool isp[5000010];
int pri[5000010],cnt=0;
void init(int n)
{
	memset(isp,1,sizeof isp);
	isp[0]=isp[1]=0;
	for(int i=2;i<=n;i++)
	{
		if(!isp[i]) continue;
		pri[++cnt]=i;
		for(int j=i*i;j<=n;j+=i) isp[j]=0;
	}
}
int ispr(int k)
{
	for(int i=2;i*i<=k;i++) if(k%i==0) return 0;
	return 1;
}
signed main()
{
	int n,k;
	cin>>n>>k;
	init(3e6);
	for(int i=1;i<=cnt;i++)
	{
		int b=pri[i],p=1;
		for(int j=1;j<=cnt;j++)
		{
			while(p<pri[j])
			{
				p++;
				b*=pri[i];
				if(b>1e18) goto t;
			}
			st.insert(b);
		}
		t:;
	}
	int tp=ceil(sqrt(n));
	for(int i=1;i<=1000;i++)
	{
		if(tp*tp>1e18) break;
		if(ispr(tp)) st.insert(tp*tp);
		tp++;
	}
	while(*(st.begin())<=n) st.erase(st.begin());
	for(int i=1;i<k;i++) st.erase(st.begin());
	cout<<*(st.begin());
	return 0;
}
posted @ 2024-01-18 19:38  Crazyouth  阅读(5)  评论(0编辑  收藏  举报