【JZOJ3188】找数

版权声明:欢迎dalao指出错误暴踩本SD,蒟蒻写的博客转载也要吱一声 https://blog.csdn.net/enjoy_pascal/article/details/89006067

description

找出第N个最小素因子是P的正整数。


analysis

  • 首先要知道大于 1 0 9 \sqrt{10^9} p p 第二个就不成立了,范围缩小了很多

  • 设第 n n 个满足条件的数是 p x p·x ,这个可以分类讨论一下

  • x x 比较大时,线筛出 [ 1 , 1 0 9 p ] [1,{10^9\over p}] 的数的最小质因数,然后扫一遍乘个 p p 判断可以知道答案

  • x x 比较小时,需要知道一个东西不想打字

=

  • 后面 1 -1 那个其实是容斥,就是奇数个的答案都减去偶数个的答案实现这个用暴力

  • 就二分 x x ,容斥加暴力求出 [ 1 , p x ] [1,px] 最小质因子的个数,然后就可以了

  • 根据数据可以发现 x = 50 x=50 左右分类较优


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 15000005
#define MAXM 1000000
#define INF 1000000000
#define ll int
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))

using namespace std;

ll prime[MAXM],s[MAXN];
ll n,p,tot,k;

O3 inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
O3 inline void init()
{
	fo(i,2,MAXN-1)
	{
		if (!s[i])prime[++tot]=i,s[i]=i;
		for (reg j=1;j<=tot && prime[j]*i<MAXN;++j)
		{
			s[prime[j]*i]=prime[j];
			if (i%prime[j]==0)break;
		}
	}
}
O3 inline ll judge(ll x)
{
	ll ans=0;
	fo(i,0,k-1)
	{
		long long temp=1ll;int cnt=0;
		for (reg tot=i,j=1;tot;tot/=2,++j)
		{
			if (tot&1)temp*=prime[j],++cnt;
		}
		ans+=(cnt&1?-1:1)*(x/temp);
	}
	return ans;
}
O3 int main()
{
	//freopen("T2.in","r",stdin);
	n=read(),p=read(),init();
	if (p>=50)
	{
		ll i=1;--n;
		while (i<=INF/p && n)
		{
			if (s[i]>=p)
			{
				--n;if (!n)break;
			}
			++i;
		}
		printf("%d\n",!n?i*p:0ll);
		return 0;
	}
	tot=0;while (prime[tot+1]<p)++tot;
	k=1<<tot;
	ll l=0,r=INF/p,ans=0;
	while (l<=r)
	{
		ll mid=(l+r)>>1;
		judge(mid)>=n?ans=mid,r=mid-1:l=mid+1;
	}
	printf("%d\n",ans*p);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/enjoy_pascal/article/details/89006067