题目链接
思路
如果第
i
i
个选手的分数没有变,那么要维持这个选手的排名,分数为的选手分数都不能变,设
c=cnt[⌈vi2⌉,vi)
c
=
c
n
t
[
⌈
v
i
2
⌉
,
v
i
)
,那么方案数就是
如果第
i
i
个选手的分数变了,那么要维持这个选手的排名,分数为的选手分数都要变,设
c=cnt[vi,2vi)
c
=
c
n
t
[
v
i
,
2
v
i
)
,那么方案数为
统计值在区间
[l,r)
[
l
,
r
)
内的个数:若
rk
r
k
为权值排好序后的结果,那么答案就是std::lower_bound(rk+1,rk+n+1,r)-std::lower_bound(rk+1,rk+n+1,l)
。
代码
#include <cstdio>
#include <algorithm>
const int maxn=100000;
const int mo=998244353;
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int n,k,v[maxn+10],fac[maxn+10],ifac[maxn+10],rk[maxn+10];
inline int c(int a,int b)
{
if((a<0)||(b<0)||(a<b))
{
return 0;
}
return 1ll*fac[a]*ifac[b]%mo*ifac[a-b]%mo;
}
inline int get(int l,int r)
{
if(l>=r)
{
return 0;
}
return std::lower_bound(rk+1,rk+n+1,r)
-std::lower_bound(rk+1,rk+n+1,l);
}
int main()
{
n=read();
k=read();
for(int i=1; i<=n; ++i)
{
v[i]=rk[i]=read();
}
std::sort(rk+1,rk+n+1);
fac[0]=1;
for(int i=1; i<=n; ++i)
{
fac[i]=1ll*fac[i-1]*i%mo;
}
ifac[0]=ifac[1]=1;
for(int i=2; i<=n; ++i)
{
ifac[i]=1ll*(mo-mo/i)*ifac[mo%i]%mo;
}
for(int i=1; i<=n; ++i)
{
ifac[i]=1ll*ifac[i-1]*ifac[i]%mo;
}
for(int i=1; i<=n; ++i)
{
if(v[i])
{
int ans=0,cnt=get((v[i]+1)>>1,v[i]);
ans+=c(n-cnt-1,k);
cnt=get(v[i],v[i]<<1);
ans+=c(n-cnt,k-cnt);
printf("%d\n",ans%mo);
}
else
{
printf("%d\n",c(n,k));
}
}
return 0;
}