UVALive 4683 Find The Number(容斥原理)

題意:k大小的元素集合,得到一個遞增數列,這個數列中的數能且僅能被這個元素集合的一個元素整除。求第n大的數。

思路:與一般的容斥不同,這裏的能整除1個元素的算了1次,能整除2個的算了2次,能整除3個的算了3次......奇加偶減。

算的過程中會爆long long,所以注意和1e15比較一下。

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;

typedef long long LL;
#define mem(a, n) memset(a, n, sizeof(a))
#define ALL(v) v.begin(), v.end()
#define si(a) scanf("%d", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define pb push_back
#define eps 1e-8
const int inf = 0x3f3f3f3f, N = 1e3 + 5, MOD = 1e9 + 7;
const LL INF = 1000000000000000LL;
int T, cas = 0;
int n, m;
LL k, ans = 0;
LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
vector<int> num;
void Inclusion_Exclusion(int idx, int cnt, LL lcm, LL b) {
	lcm = (LL)num[idx] * lcm / gcd((LL)num[idx], lcm);
	if(lcm > INF) return;
	if(cnt & 1) ans += b / lcm * cnt;
	else ans -= b / lcm * cnt;
	for(int i = idx + 1; i < n; i ++)
		Inclusion_Exclusion(i, cnt + 1, lcm, b);
}

int main(){
#ifdef LOCAL
    freopen("/Users/apple/input.txt", "r", stdin);
//	freopen("/Users/apple/out.txt", "w", stdout);
#endif
	
	si(T);
	while(T --) {
		int x;
		scanf("%d%lld", &n, &k);
		num.clear();
		for(int i = 0 ; i < n ; i ++) {
			si(x);
			num.pb(x);
		}
		LL l = 1, r = INF;
		while(l < r - 1) {
			LL mid = (l + r) >> 1;
			ans = 0;
			for(int i = 0; i < n; i ++)
				Inclusion_Exclusion(i, 1, 1, mid);
			if(ans < k) l = mid;
			else r = mid;
		}

		printf("%lld\n", r);
	}
    
    return 0;
}


發佈了115 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章