根据数据范围猜解法,数据分治!!!【x
好吧……其实是先想到了容斥的,然而容斥姿势不太好果断GG没写,反正觉得容斥的话p肯定不能太大,然后又yy了循环节啥的各种鬼畜东西233333(虽然最后发现根本没什么卵用
然后在考试结束前几分钟被小朋友嘲讽,忽然就想到了怎么写p比较大的,在线性筛的时候,顺手记录每个数的最小质因子,因为p大,所以p的系数应该是很小的,于是直接枚举,如果枚举到的数的最小质因子大于等于p就++cnt,最后cnt==n的时候break
容斥的时候可以用dfs,乘上当前的数如果比n大就直接continue,剪了一堆枝
我应该是写挂了…………反正数据水23333
#include<bits/stdc++.h>
#define INF 1000000000
#define MAXN 2000005
using namespace std; int n,p;
int tag[MAXN] , prime[MAXN];
void get_prime(int x){
for(int i=2;i<=x;++i){
if(!tag[i]) prime[++prime[0]] = i , tag[i] = i;
for(int j=1;j<=prime[0];++j){
if(1ll*i*prime[j]>x) break;
tag[i*prime[j]] = prime[j];
if(!(i%prime[j])) break;
}
}
// for(int i=0;i<=prime[0];++i) printf("%d\n",prime[i]);
}
int tmp;
void dfs(int x,int pos,int pro,int k){
if(!pos) tmp += x/pro *k;
else{
dfs(x,pos-1,pro,k);
if(1ll*pro*prime[pos]<=x)
dfs(x,pos-1,pro*prime[pos],-k);
}
}
void sol(){
get_prime(p);
int pos = prime[0];
int l = p*p , r = INF+1;
while(l^r){
int mid = (l+r)>>1;
tmp = 0;
dfs(mid/p,pos-1,1,1);
if(tmp<n) l = mid+1;
else r = mid;
}
printf("%d",l>INF?0:l);
}
int main(){
// freopen("broj.in","r",stdin);
// freopen("broj.out","w",stdout);
scanf("%d%d",&n,&p);
if(n==1) return printf("%d",p),0;
if(1ll*n*p>INF) return puts("0"),0;
if(p==2){
long long ans = 2ll*n;
printf("%lld",ans>INF?0ll:ans);
return 0;
}
if(p>=500){
get_prime(2000000);
for(int i=p,j=1;i<=2000000;++i){
if(tag[i]>=p) ++j;
if(j==n)
return printf("%d",1ll*i*p>INF?0:i*p),0;
}
}
else
sol();
return 0;
}