「PKUSC2018」真实排名

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

若翻倍,则\(\text{[$a_i$ ,2$a_i$ -1]}\)内的数必须翻倍,要不然会影响答案。
若不翻倍,则\(\text{[$\lceil \frac{a_i}{2} \rceil$, $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\n", 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\n", ans);
    }

#ifdef LiM_817
    cerr << fixed << setprecision(2) << "Time ellapsed: " << ((double)(clock() - cl) / CLOCKS_PER_SEC) << "s\n";
#endif
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LiM-817/p/11903483.html