题目链接
https://loj.ac/problem/6432
思路
如果第ii个选手的分数没有变,那么要维持这个选手的排名,分数为[⌈vi2⌉,vi)[⌈vi2⌉,vi)的选手分数都不能变,设c=cnt[⌈vi2⌉,vi)c=cnt[⌈vi2⌉,vi),那么方案数就是
(n−c−1k)(n−c−1k)
如果第ii个选手的分数变了,那么要维持这个选手的排名,分数为[vi,2vi)[vi,2vi)的选手分数都要变,设c=cnt[vi,2vi)c=cnt[vi,2vi),那么方案数为
(n−ck−c)(n−ck−c)
统计值在区间[l,r)[l,r)内的个数:若rkrk为权值排好序后的结果,那么答案就是std::lower_bound(rk+1,rk+n+1,r)-std::lower_bound(rk+1,rk+n+1,l)
。
代码
#include
#include
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)||(areturn 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;
}