[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;
}
posted @ 2019-06-01 20:19  asuldb  阅读(220)  评论(0编辑  收藏  举报