codeforces 1436C - Binary Search (二分 + 組合計數)
阿新 • • 發佈:2020-10-25
題目連結:https://codeforces.com/problemset/problem/1436/C
先在有序序列二分查詢 pos ,統計出按二分路徑分別需要向左和向右查詢的次數
向左查詢即該位置的數比 x 大,向右查詢即該位置數比 x 小
也就是從比 x 大的數中選出 cntr 個,比 x 小的數中選出 cntl 個,
最後再分別乘上排列數即可
階乘和階乘逆元
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #include<stack> #include<queue> using namespace std; typedef long long ll; const int maxn = 1010; const int M = 1000000007; int n,x,pos; int a[maxn]; ll fac[maxn],ifac[maxn]; ll qsm(ll i,ll po){ ll res = 1; while(po){ if(po & 1) res = 1ll * res * i % M; po >>= 1; i = 1ll * i * i % M; } return res; } ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } int main(){ fac[0] = 1ll; int N = 1000; for(int i=1;i<=N;++i) fac[i] = 1ll * fac[i-1] * i % M; ifac[N] = qsm(fac[N],M-2); for(int i=N-1;i>=0;--i){ ifac[i] = 1ll * ifac[i+1] * (i+1) % M; } n = read(), x = read(), pos = read();// ++pos; for(int i=0;i<n;++i) a[i] = i; int l = 0, r = n; int cntl = 0, cntr = 0; while(l<r){ int mid=(l+r)/2; if(a[mid] <= pos){ l = mid + 1; if(a[mid] != pos) ++cntl; } else{ r = mid; ++cntr; } } int tl = x - 1, tr = n - x; if(tr < cntr || tl < cntl){ printf("0\n"); } else{ ll ans = 0; ans = 1ll * fac[tr] * ifac[cntr] % M * ifac[tr-cntr] % M * fac[tl] % M * ifac[cntl] % M * ifac[tl-cntl] % M * fac[cntr] % M * fac[cntl] % M * fac[n-1-cntl-cntr] % M; printf("%lld\n",ans); } return 0; }