根據數據範圍猜解法,數據分治!!!【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;
}