【Amritapuri 2009】 Find the Number

来源:互联网 发布:删除列的sql 编辑:程序博客网 时间:2024/06/14 01:32

【题目大意】

给定k个数p1,p2,,,pk,给定n,求第n大的数,满足有且仅有一个序列p中的数整除它。给定的p两两互质。

(k<=12,n<232,2<=pi<=105)


【分析】

二分答案+容斥判定

其实看到k的范围就应该想到枚举子集来容斥了。


【题目】

/* Ciocio's Oi Template */#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <iostream>#include <algorithm>#include <queue>using namespace std;#define rep(i,a,b) for(int i=(a);i<=(b);++i)#define rrep(i,b,a) for(int i=(b);i>=(a);--i)#define ll long long#define pf printf#define sf scanf#define INF (~0Ull>>3)#define MAXK 20ll K,N;ll A[MAXK];ll lcm[1<<13];ll cnt[1<<13];ll Gcd(ll a,ll b){return b?Gcd(b,a%b):a;}ll Lcm(ll a,ll b){return a/Gcd(a,b)*b;}void Get(){rep(s,1,(1<<K)-1){ll lcmm=1;ll cntt=0;rep(i,0,K-1){if((s>>i)&1){++cntt;lcmm=Lcm(lcmm,A[i]);}}lcm[s]=lcmm;cnt[s]=cntt;}}void Init(){rep(i,0,K-1){sf("%lld",&A[i]);}Get();}ll Cal(ll n){ll rt=0;rep(s,1,(1<<K)-1){ll tmp=(n/lcm[s])*cnt[s];rt+=(cnt[s]&1)?tmp:-tmp;}return rt;}void Solve(){ll Left=2,Right=INF,Mid;ll rt;while(Left<=Right){Mid=(Left+Right)>>1;if(Cal(Mid)>=N){rt=Mid;Right=Mid-1;}else{Left=Mid+1;}}pf("%lld\n",rt);}int main(){int T;while(~sf("%lld",&T)){while(T--){sf("%lld%lld",&K,&N);        Init();        Solve();    }}return 0;}


0 0
原创粉丝点击