루오 구 [5368] [PKUSC2018] 실제 랭킹 (조합론)

문제의 표면을 보려면 여기를 클릭하십시오

일반적으로 문제의 의미 가있다 \ (N- \) 숫자는 순위 번호가 숫자의 수보다 작지 정의합니다. 지금 무작위 될 것입니다 어느 \ (K \) 를 곱한 숫자 \ (2 \) , 프로그램의 많은 종류가 각 번호에 대해 동일한 순위를 확인하는 방법을 찾을 수 있습니다.

분류 토론

이 문제에 대한, 우리는 그의 경상 가정, 분류에 대해 얘기 할 수 있습니다 \ (I \) 응답 수입니다.

\ (A_I이 \) 원래 때부터하지 수정할 수있다 (\ GE의 A_I \) \ 수 후 수정할 수없는 \ (<A_I \) , 우리가 알 수 있습니다 :

  • 원래는 \ (\ GE의 A_I \) 수를 자유롭게 수정할 수 있습니다.
  • 원래 \ (<A_I \) 수 후 수정하면 \ (\ GE의 A_I \) 변경할 수 없습니다.

만약 우리 정렬 원래 시퀀스 제공 \ (T1 \) 를 만족 \ (2a_ {T1} <A_I \ 르 2a_ T1 +. 1 {} \) , 다음 번호가 수정되지 않을 수 (I-T1 \) \ A, 반면 나머지 \ (N- (I-T1) \) 번호가 변경 될 수있다, 즉, 프로그램의 수 :

\ [C_ {N (I-T1)} K ^ \]

\ (A_I이 \) 수정 때문에 원래 \ (<A_I \) 번호 피할 여전히 수정 후 \ (<A_I \)를 우리가 알 수 있도록 :

  • 원래는 \ (<A_I \) 수를 자유롭게 수정할 수 있습니다.
  • 원래는 \ (\ ge2a_i \) 수를 자유롭게 수정할 수 있습니다.
  • 원래 \ (\ GE의 A_I \)\ (<2a_i \) 수를 수정해야합니다.

우리 정렬 원래 시퀀스 제공된 경우 \ (T2 \) 를 만족 \ (T2 A_ {} <2a_i \ A_ 르 T2 +. 1 {} \) , 다음이 수정되어야 번호 \ (T2-I + 1 \ ) 한 (참고 \ (A_I \) 수정해야 함), 나머지 \ (N- (T2-I + 1) \) 번호가 변경 될 수있다, 즉, 프로그램의 수 :

\ [C_ {N- (T2-I + 1)} ^ {K- (T2-I + 1)} \]

를 들어 \ (T1, T2 \) , 우리는 열거 할 수 있습니다 (I \) \ 동시에 유지 보수.

특수 상황

참고이 특별한 경우가 있음 위의 추론 카드 밖으로 것.

  • \ (A_I = 0 \) .
    • 질문 : 우리는에 따르면,이 찾을 \ (T2는 \) 이 경우, 정의 \ (T2 <I \) , 이동합니다.
    • 해결 방법 : 매번 \ (T2 \)\ (나는 \) 합니다 \ (\ 최대) .
  • 같은 나타나지 \ (A_I을 \) .
    • 질문 : 토론의 과정이 경계의 세부 사항 중 일부에 패닝에서.
    • 해결 방법 : 어려운, 같은 찾을 수 있습니다 (\ A_I를) \ 대답은 동일합니다. 동일의 일부 \ (A_I \) 상기 제 1, 제 \ (A_I \) 에러에 응답하지 않는 상기 방법에 의해 산출된다. 그래서 모든 같은 \ (A_I는 \) 처음에 대한 송시 응답 \ (A_I \) 에 대한 답변.

코드

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg 
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define X 998244353
#define C(x,y) ((x)>=(y)?1LL*Fac[x]*IFac[y]%X*IFac[(x)-(y)]%X:0)
using namespace std;
int n,k,ans[N+5],Fac[N+5],IFac[N+5];
struct data {int p,v;I bool operator < (Con data& o) Con {return v<o.v;}}s[N+5];
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int main()
{
    RI i,t1,t2,lst;for(scanf("%d%d",&n,&k),Fac[0]=i=1;i<=n;++i) Fac[i]=1LL*Fac[i-1]*i%X;//预处理阶乘
    for(IFac[n]=Qpow(Fac[n],X-2),i=n-1;~i;--i) IFac[i]=1LL*IFac[i+1]*(i+1)%X;//预处理阶乘逆元
    for(i=1;i<=n;++i) scanf("%d",&s[s[i].p=i].v);//读入
    for(sort(s+1,s+n+1),s[0].v=-1,i=1,t1=t2=0;i<=n;++i)//记得排序
    {
        if(s[i].v==s[i-1].v) {ans[s[i].p]=lst;continue;}//如果与上一个数一样
        W(t1^n&&2*s[t1+1].v<s[i].v) ++t1;W(t2^n&&s[t2+1].v<2*s[i].v) ++t2;t2<i&&(t2=i);//更新t1,t2
        ans[s[i].p]=lst=(C(n-(i-t1),k)+(t2-i<=k?C(n-(t2-i+1),k-(t2-i+1)):0))%X;//计算答案
    }
    for(i=1;i<=n;++i) printf("%d\n",ans[i]);return 0;//输出答案
}

추천

출처www.cnblogs.com/chenxiaoran666/p/Luogu5368.html