[PKUSC2018]真实排名
组合数大模拟,没什么好说的,注意一下\(0\)的特判
还有我现在码力真的差
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
const int maxn=100005;
const int mod=998244353;
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct Person{int x,rk;}a[maxn];
int n,m;
int fac[maxn],inv[maxn],ifac[maxn],ans[maxn];
inline int C(int n,int m) {
if(n<m) return 0;
if(n<0||m<0) return 0;
return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
inline int cmp(Person A,Person B) {return A.x<B.x;}
inline int find(int k) {
int l=1,r=n,p=0;
while(l<=r) {
int mid=l+r>>1;
if(a[mid].x>=k) p=mid,r=mid-1;
else l=mid+1;
}
return p?n-p+1:0;
}
inline int chk(int k) {
int l=1,r=n,p=0;
while(l<=r) {
int mid=l+r>>1;
if(a[mid].x<k) p=mid,l=mid+1;
else r=mid-1;
}
return p;
}
int main() {
n=read(),m=read();
fac[0]=1;inv[1]=1;ifac[0]=1;
for(re int i=1;i<=n;i++) fac[i]=1ll*i*fac[i-1]%mod;
for(re int i=2;i<=n;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(re int i=1;i<=n;i++) ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
for(re int i=1;i<=n;i++) a[i].x=read(),a[i].rk=i;
std::sort(a+1,a+n+1,cmp);int now=0,st=1;
for(re int i=1;i<=n;i++) {
if(i>1&&a[i].x>a[i-1].x) st=i;
while(a[now+1].x*2<a[i].x&&now<n) now++;
ans[a[i].rk]=C(n-st+now,m);
int t=find(a[i].x*2)+1;
if(!a[i].x) --t;
int tot=chk(a[i].x*2)-st,fan=0;
if(!a[i].x) tot=0;
fan=n-st+1-t;
ans[a[i].rk]=(ans[a[i].rk]+1ll*C(tot,fan)*C(n-tot-1,m-1-fan)%mod)%mod;
}
for(re int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}