「PKUSC2018」真实排名

分类讨论这个数((a_i))翻不翻倍。

若翻倍,则( ext{[)a_i$ ,2(a_i) -1]}(内的数必须翻倍,要不然会影响答案。 若不翻倍,则) ext{[(lceil frac{a_i}{2} ceil), (a_i-1)]}$内的数必须不翻倍,要不然也会影响答案。

剩下的计算可以组合数解决,注意特判(a_i=0)的时候要输出(C_n^k)

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;

#define LOG(...) fprintf (stderr, __VA_ARGS__)
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(), (x).end()

const int INF = 0x3f3f3f3f, MOD = 998244353;
const LL INFL = 0x3f3f3f3f3f3f3f3fll;

const int N = 100005; 
int n, k, a[N], b[N], fac[N], ifac[N]; 
int binom (int n, int m) {
	if (n < m || n < 0 || m < 0) return 0; 
	return 1LL * fac[n] * ifac[n - m] % MOD * ifac[m] % MOD;
}
int inv (int x) {
	int t = MOD - 2, res = 1; 
	while (t) {
		if (t&1) res = 1LL * res * x % MOD;
		x = 1LL * x * x % MOD;
		t >>= 1; 
	}
	return res; 
}
void work() {
	fac[0] = 1; 
	for (int i = 1; i <= n; i++) fac[i] = 1LL * fac[i - 1] * i % MOD;
	ifac[n] = inv(fac[n]);
	for (int i = n-1; i >= 0; i--) ifac[i] = 1LL * ifac[i + 1] * (i + 1) % MOD;
}
int Q (LL x) {
	if (x < b[1]) return 0;
	int l = 1, r = n, ans = 0;
	while (l <= r) {
		int mid = (l + r) >> 1;
		if (b[mid] <= x) ans = mid, l = mid + 1;
		else r = mid - 1;
	}
	return ans; 
}

int add (int a, int b) {
	int val = a + b;
	if (val >= MOD) val -= MOD;
	return val; 
}
int main() {
#ifdef LiM_817
	freopen ("input.txt", "r", stdin);
//	freopen ("test.out", "w", stdout);
	double cl = clock();
#endif

	cin >> n >> k;
	for (int i = 1; i <= n; i++) scanf ("%d", &a[i]), b[i] = a[i];
	sort (b + 1, b + n + 1);
	work();
	
	for (int i = 1; i <= n; i++) {
		if (!a[i]) {
			printf ("%d
", binom (n, k)); 
			continue;
		}
		
		int ans = 0; 
		// case 1
		int Lb = a[i] / 2 + (a[i] % 2), Rb = a[i] - 1;
		if (Lb > Rb) ans = add(ans, binom (n - 1, k));
		else {
			int q = Q(Rb) - Q(Lb - 1);
			ans = add(ans, binom (n - 1 - q, k));
		}
		
		Lb = a[i], Rb = 2 * a[i] - 1;
		if (Lb > Rb) ans = add (ans, binom (n - 1, k - 1));
		else {
			int q = Q(Rb) - Q(Lb - 1);
			ans = add (ans, binom (n - q, k - q));
		}
		printf ("%d
", ans);
	}

#ifdef LiM_817
	cerr << fixed << setprecision(2) << "Time ellapsed: " << ((double)(clock() - cl) / CLOCKS_PER_SEC) << "s
";
#endif
	return 0;
}
原文地址:https://www.cnblogs.com/LiM-817/p/11903483.html