题解:
先枚举出所有数可能搭配出的最小公倍数,再二分一下答案,进行判断是否合法,判断就用容斥原理乱搞就行了
#include<bits/stdc++.h>
using namespace std;
long long n,k;
const long long maxans= 1e15;
long long a[20];
long long read(){
long long num=0;
char ch=getchar();
while(ch>'9'||ch<'0'){
ch=getchar();
}
while(ch>='0'&&ch<='9'){
num=(num<<1)+(num<<3)+ch-'0';
ch=getchar();
}
return num;
}
struct oo{
long long num;
long long cnt;
}nn[1000000];
long long idx;
int gcd(int x,int y){
if(y==0) return x;
if(x==0) return y;
return gcd(y,x%y);
}
void pre(long long deep,long long st,long long own){
long long j=1;
if(deep){
nn[++idx].num=own,nn[idx].cnt=deep;
}
for(long long i=st+1;i<=n;i++){
if(deep){
j=own*a[i]/gcd(own,a[i]);
}
else j=a[i];
if(j>maxans) continue;
pre(deep+1,i,j);
}
}
long long calc(long long x){
long long sum=0;
for(int i=1;i<=idx;i++){
if(nn[i].cnt&1){
sum+=x/nn[i].num*nn[i].cnt;
}
else sum-=x/nn[i].num*nn[i].cnt;
}
return sum;
}
int main(){
n=read(),k=read();
for(long long i=1;i<=n;i++){
a[i]=read();
}
pre(0,0,1);
long long l=1,r=maxans;
while(l<=r){
long long mid=(l+r)>>1;
long long own=calc(mid);
if(own<k){
l=mid+1;
}
else{
if(own>k) r=mid-1;
else {
if(calc(mid-1)==own){
r=mid-1;
}
else l=mid+1;
}
}
}
cout<<r<<endl;
}