[LOJ 6432] [2018 PKUSC] 실제 랭킹
문제의 의미
주어 (N \) \ 경쟁사의 점수는 중 하나를 선택합니다 \ (케이 \)를 이중 자신의 성취를한다. 각 참가자는 프로그램의 많은 종류의 자신의 순위가 변경되지 않습니다 만드는 방법에 답이 들어.
\ (N \ 10 ^ 5 \)
문제 해결
질문 중 독특한 법원?
우리는 두 가지 유형을 논의, 하나는 현재의 선수를 두 배로하는 것입니다, 하나는 두 배가되지 않습니다.
- 현재 플레이어가 두 배가되지 않으면, 그래서 더 모든 선수가 두 배가 될 수 없다 후 현재 플레이어를 두 배로보다, 다른 사람은 무료입니다. 프로그램의 수는 선택된 사람들의 나머지 부분에서 분명히 \ (케이 \) 프로그램의 개월 수.
- 현재 플레이어가 두 배가되면, 두 배 이상이어야합니다 모든 선수 이후 두 배로, 다른 사람은 무료. 프로그램 번호는 조합의 숫자입니다.
이렇게 모래 조각에 대한 질문. 난 정말에만이 문제의 모래 조각을 필드 수 있습니다.
참조 코드
#include <bits/stdc++.h>
const int MAXN=1e5+10;
const int MOD=998244353;
int n;
int k;
int a[MAXN];
int s[MAXN];
int h[MAXN];
int d[MAXN];
int inv[MAXN];
int fact[MAXN];
int ReadInt();
int C(int,int);
int Pow(int,int,int);
int main(){
n=ReadInt();
k=ReadInt();
for(int i=1;i<=n;i++)
s[i]=a[i]=ReadInt();
std::sort(s+1,s+n+1);
fact[0]=1;
for(int i=1;i<=n;i++)
fact[i]=1ll*fact[i-1]*i%MOD;
inv[n]=Pow(fact[n],MOD-2,MOD);
for(int i=n;i>=1;i--)
inv[i-1]=1ll*inv[i]*i%MOD;
for(int i=1;i<=n;i++){
if(a[i]==0)
printf("%d\n",C(n,k));
else{
int ans=0;
int d=std::lower_bound(s+1,s+n+1,a[i])-std::lower_bound(s+1,s+n+1,(a[i]+1)/2);
(ans+=C(n-d-1,k))%=MOD;
d=std::lower_bound(s+1,s+n+1,a[i]*2)-std::lower_bound(s+1,s+n+1,a[i]);
(ans+=C(n-d,k-d))%=MOD;
printf("%d\n",ans);
}
}
return 0;
}
int C(int n,int m){
return n<m||n<0||m<0?0:1ll*fact[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int Pow(int a,int n,int p){
int ans=1;
while(n>0){
if(n&1)
ans=1ll*a*ans%p;
a=1ll*a*a%p;
n>>=1;
}
return ans;
}
inline int ReadInt(){
int x=0;
register char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch)){
x=x*10+ch-'0';
ch=getchar();
}
return x;
}