BZOJ5368-[Pkusc2018]真实排名

5368: [Pkusc2018]真实排名

Time Limit: 10 Sec   Memory Limit: 256 MB

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)翻倍,他的排名会变成第二,其他情况下都还是第一。

是一道水题!

是一道水题!!

是一道水题!!!

分两种情况讨论,不翻倍的话,≤a/2或≥a的随意选k个,翻倍的话,≥a且<2a的数必须翻倍。

不愿多说。

Code:

#include<iostream> 
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define N 100005
#define mod 998244353
using namespace std;
int n,k;
ll fac[N],inv[N],b[N];
struct node
{
	int val,num,l;
}a[N];
int cmp(node x,node y)
{
	if(x.val==y.val)return x.num<y.num;
	return x.val<y.val;
}
int C(int n,int m)
{
	if(m<0||m>n)return 0;
	return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int eftw(int l,int r,int k)
{
	if(l==r)return l;
	int mid=(l+r+1)>>1;
	if(a[mid].val<k)return eftw(mid,r,k);else
		return eftw(l,mid-1,k);
}
int efha(int l,int r,int k)
{
	if(l==r)return l;
	int mid=(l+r)>>1;
	if(a[mid].val>=k)return efha(l,mid,k);else
		return efha(mid+1,r,k);
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%d",&a[i].val);
	for(int i=1;i<=n;i++)a[i].num=i;
	sort(a+1,a+1+n,cmp);
	a[1].l=1;
	for(int i=2;i<=n;i++)
		if(a[i].val==a[i-1].val)a[i].l=a[i-1].l;else a[i].l=i;
    fac[0]=inv[0]=inv[1]=1;
    for(int i=1;i<=N;i++)fac[i]=1ll*fac[i-1]*i%mod;
    for(int i=2;i<=N;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1;i<=N;i++)inv[i]=1ll*inv[i-1]*inv[i]%mod;
    //for(int i=1;i<=n;i++)cout<<a[i].val<<" ";cout<<endl;
    for(int i=1;i<=n;i++)
    {
    	int tw=eftw(1,n,a[i].val*2);
    	ll ans1=C(n-tw+a[i].l-1,k-(tw-a[i].l)-1);
    	int ha=efha(1,n,(a[i].val+1)/2);
    	ll ans2=C(ha+n-a[i].l-1,k);
    	ll ans=(ans1+ans2)%mod;
    	//cout<<tw<<" "<<ha<<endl;
    	b[a[i].num]=ans;
	}
	for(int i=1;i<=n;i++)printf("%lld\n",b[i]);
}

猜你喜欢

转载自blog.csdn.net/qq_34531807/article/details/80615655
今日推荐