【NOIP模擬】number

在這裏插入圖片描述

題解:

先枚舉出所有數可能搭配出的最小公倍數,再二分一下答案,進行判斷是否合法,判斷就用容斥原理亂搞就行了

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章