zoukankan      html  css  js  c++  java
  • BZOJ5368:[PKUSC2018]真实排名(组合数学)

    Description

    小C是某知名比赛的组织者,该比赛一共有n名选手参加,每个选手的成绩是一个非负整数,定义一个选手的排名是:成绩不小于他的选手的数量(包括他自己)。
    例如如果333位选手的成绩分别是[1,2,2],那么他们的排名分别是[3,2,2]。
    拥有上帝视角的你知道所有选手的实力,所以在考试前就精准地估计了每个人的成绩,设你估计的第iii个选手的成绩为Ai,且由于你是上帝视角,所以如果不发生任何意外的话,你估计的成绩就是选手的最终成绩。
    但是在比赛当天发生了不可抗的事故(例如遭受到了外星人的攻击),导致有一些选手的成绩变成了最终成绩的两倍,即便是有上帝视角的你也不知道具体是哪些选手的成绩翻倍了,唯一知道的信息是这样的选手恰好有k个。
    现在你需要计算,经过了不可抗事故后,对于第i位选手,有多少种情况满足他的排名没有改变。
    由于答案可能过大,所以你只需要输出答案对998244353取模的值即可。

    Input

    第一行两个正整数n,k
    第二行n个非负整数A1..An
    1≤k<n≤10^5 ,0≤Ai≤10^9

    Output

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

    Sample Input

    3 2
    1 2 3

    Sample Output

    3
    1
    2
    样例解释
    一共有3种情况:(1,2)翻倍,(1,3)翻倍,(2,3)翻倍。
    对于第一个选手来说,他的成绩就算翻倍,其他人都不低于他,所以任意情况下他的排名都不会改变。
    对于第二个选手来说,如果是(1,2)翻倍,成绩变成(2,4,3),他的排名变成了第一;
    如果是(1,3)翻倍,则成绩变成(2,2,6),他的排名变成了第三;如果是(2,3)翻倍,则成绩变成(1,4,6),他的排名还是第二。
    所以只有一种情况。
    对于第三个选手来说,如果是(1,2)翻倍,他的排名会变成第二,其他情况下都还是第一。

    Solution

    传说中的送温暖签到题QAQ?$pkuwc$的时候咋没有呢……

    先把数$sort$一下,然后一个一个考虑。

    对于当前数$b[i]$,分两种情况(如果$b[i]=b[i-1]$就答案等于前一个数的答案然后$continue$):

    1、本身不翻倍,那么只有$b[i]$前面的某一段数是一定不能选的,因为如果选了这一段数的话就会有数超过$b[i]$从而改变排名……二分找一下就好了。

    2、$b[i]$本身翻倍,这样$b[i]$后面的某一段数就必须得翻倍把$b[i]$翻下来,不然排名仍然会变。仍然二分找一下。

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<map>
     4 #include<algorithm> 
     5 #define N (100009)
     6 #define MOD (998244353)
     7 using namespace std;
     8 
     9 struct Node{int x,id,ans;}a[N];
    10 int n,k,x,pos,b[N],inv[N],fac[N],facinv[N];
    11 bool cmp1(Node a,Node b) {return a.x<b.x;}
    12 bool cmp2(Node a,Node b) {return a.id<b.id;}
    13 
    14 void Init()
    15 {
    16     inv[1]=fac[0]=facinv[0]=1;
    17     for (int i=1; i<=n; ++i)
    18     {
    19         if (i!=1) inv[i]=1ll*(MOD-MOD/i)*inv[MOD%i]%MOD;
    20         fac[i]=1ll*fac[i-1]*i%MOD; facinv[i]=1ll*facinv[i-1]*inv[i]%MOD;
    21     }
    22 }
    23 
    24 int C(int n,int m)
    25 {
    26     if (n<m) return 0;
    27     return 1ll*fac[n]*facinv[m]%MOD*facinv[n-m]%MOD;
    28 }
    29 
    30 int main()
    31 {
    32     scanf("%d%d",&n,&k);
    33     Init();
    34     for (int i=1; i<=n; ++i)
    35         scanf("%d",&a[i].x), a[i].id=i;
    36     sort(a+1,a+n+1,cmp1);
    37     for (int i=1; i<=n; ++i) b[i]=a[i].x;
    38     
    39     b[0]=-1;
    40     for (int i=1; i<=n; ++i)
    41     {
    42         if (b[i]==b[i-1]) {a[i].ans=a[i-1].ans; continue;}
    43         
    44         x=b[i]/2+(b[i]%2);//自己不翻倍
    45         pos=lower_bound(b+1,b+i,x)-b; 
    46         a[i].ans=(a[i].ans+C(pos-1+n-i,k))%MOD;//[pos,i-1]不能翻倍,再算上i本身
    47         
    48         x=b[i]*2;//自己翻倍
    49         pos=lower_bound(b+i+1,b+n+1,x)-b;
    50         pos--;//[i+1,pos]要翻倍
    51         if (pos-i>k-1) continue;
    52         a[i].ans=(a[i].ans+C(i-1+n-pos,k-1-(pos-i)))%MOD;
    53     }
    54     sort(a+1,a+n+1,cmp2);
    55     for (int i=1; i<=n; ++i)
    56         printf("%d
    ",a[i].ans);
    57 } 
  • 相关阅读:
    Django~1
    Codeforces Round#201(div1) D. Lucky Common Subsequence
    ACdream原创群赛(18)のAK's dream题解
    区间dp
    部署AlwaysOn第三步:集群资源组的健康检测和故障转移
    Join 和 App
    SSRS配置1:凭证和邮件
    巧用Alt 键
    把Excel的数据导入到数据库
    jvm系列:Java GC 分析
  • 原文地址:https://www.cnblogs.com/refun/p/10152786.html
Copyright © 2011-2022 走看看