Loading [MathJax]/jax/output/CommonHTML/jax.js

【LOJ4632】[PKUSC2018]真实排名

【LOJ4632】[PKUSC2018]真实排名

题面

终于有题面啦!!!

题目描述

小 C 是某知名比赛的组织者,该比赛一共有 n 名选手参加,每个选手的成绩是一个非负整数,定义一个选手的排名是:成绩不小于他的选手的数量(包括他自己)。例如如果 3 位选手的成绩分别是 [1,2,2] ,那么他们的排名分别是 [3,2,2]

拥有上帝视角的你知道所有选手的实力,所以在考试前就精准地估计了每个人的成绩,设你估计的第 i 个选手的成绩为Ai​,且由于你是上帝视角,所以如果不发生任何意外的话,你估计的成绩就是选手的最终成绩。

但是在比赛当天发生了不可抗的事故(例如遭受到了外星人的攻击),导致有一些选手的成绩变成了最终成绩的两倍,即便是有上帝视角的你也不知道具体是哪些选手的成绩翻倍了,唯一知道的信息是这样的选手恰好有 k 个。

现在你需要计算,经过了不可抗事故后,对于第 i 位选手,有多少种情况满足他的排名没有改变。

由于答案可能过大,所以你只需要输出答案对 998244353 取模的值即可。

输入格式

第一行两个正整数 n,k

第二行 n 个非负整数 A1..An

输出格式

输出n行,第 i 行一个非负整数 ansi​,表示经过不可抗事故后,第 i 位选手的排名没有发生改变的情况数。

样例

样例输入

3 2
1 2 3
BASIC

输出

3
1
2
Undefined

提示与说明

对于10%的数据,有 1n151

对于35%的数据,有 1n103

另有10%的数据,满足每个人的成绩都互不相同

另有10%的数据,满足Ai105

另有10%的数据,满足k=850Ai6000

对于100%的数据,有1k<n1050Ai109

题解

其实还是挺容易的qaq,只不过细节比较多

分别考虑你现在计算的那个位置选不选

如果不选,可以选比它大的或小于它12的。

那么假如我们钦定它选,则必须动[ai,2ai]的,

计算一下有多少,其余的随便选就行了。

每一种情况都预处理阶乘用组合数就好啦

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar();
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
    return w * data; 
}
const int Mod = 998244353; 
const int MAX_N = 1e5 + 5;
int fpow(int x, int y) { 
    int res = 1;
    while (y) {
        if (y & 1) res = 1ll * res * x % Mod; 
        y >>= 1; 
        x = 1ll * x * x % Mod; 
    } 
    return res; 
} 
int N, K, A[MAX_N], fac[MAX_N << 1], inv[MAX_N << 1]; 
int C(int n, int m) {
    if (m > n || m < 0) return 0; 
    return 1ll * fac[n] * inv[m] % Mod * inv[n - m] % Mod;
} 
int X1[MAX_N], X2[MAX_N], ans[MAX_N]; 

int main () { 
    N = gi(), K = gi(); 
    fac[0] = 1; for (int i = 1; i <= 2 * N; i++) fac[i] = 1ll * fac[i - 1] * i % Mod; 
    inv[2 * N] = fpow(fac[2 * N], Mod - 2); for (int i = 2 * N - 1; ~i; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % Mod; 
    for (int i = 1; i <= N; i++) A[i] = gi(), X1[i] = A[i], X2[i] = A[i] << 1; 
    sort(&X1[1], &X1[N + 1]); 
    sort(&X2[1], &X2[N + 1]); 
    for (int i = 1; i <= N; i++) {
        if (A[i] == 0) { ans[i] = C(N, K); continue; } 
        int x = N - 1 - (lower_bound(&X2[1], &X2[N + 1], A[i]) - X2 - 1) - (N - (lower_bound(&X1[1], &X1[N + 1], A[i]) - X1)); 
        int y = (N - (lower_bound(&X1[1], &X1[N + 1], A[i]) - X1) + 1) - 1 - (N - (lower_bound(&X1[1], &X1[N + 1], A[i]) - X1)); 
        ans[i] = C(x, y) * C(N - 1 - x, K - y) % Mod; 
    }
    for (int i = 1; i <= N; i++) {
        if (A[i] == 0) continue;
        int x = N - 1 - (lower_bound(&X2[1], &X2[N + 1], A[i] << 1) - X2 - 1) - (N - (lower_bound(&X1[1], &X1[N + 1], A[i] << 1) - X1) + 1); 
        int y = N - (lower_bound(&X1[1], &X1[N + 1], A[i]) - X1) - (N - (lower_bound(&X1[1], &X1[N + 1], A[i] << 1) - X1) + 1); 
        ans[i] = (ans[i] + C(x, y) * C(N - 1 - x, K - y - 1) % Mod) % Mod;
    }
    for (int i = 1; i <= N; i++) printf("%d\n", ans[i]); 
    return 0; 
} 
C++
posted @   heyujun  阅读(190)  评论(0编辑  收藏  举报
编辑推荐:
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 2025成都.NET开发者Connect圆满结束
点击右上角即可分享
微信分享提示