1. 程式人生 > 實用技巧 >Codeforces Round #678 (Div. 2) C. Binary Search (二分,組合數)

Codeforces Round #678 (Div. 2) C. Binary Search (二分,組合數)

  • 題意:有長度\(n\)的序列,讓你構造序列,使得二分查詢能在\(pos\)位置找到值\(x\).問最多能構造出多少種排列?

  • 題解:題目給出的\(pos\)是固定的,所以我們可以根據圖中所給的程式碼來進行二分,確定有多少數小於\(x\)和大於\(x\),然後根據排列組合即可算出答案.

  • 程式碼:

    int n,x,pos;
    ll fac[N];
    
    ll f[N],invf[N];
    ll fpow(ll a,ll k){
    	ll res=1;
    	while(k){
    		if(k&1) res=(res*a)%mod;
    		k>>=1;
    		a=a*a%mod;
    		//cout<<1<<endl;
    	}
    	return res;
    }
    
    void init(int n){
    	f[0]=1;
    	for(int i=1;i<=n;++i){
    		f[i]=f[i-1]*i%mod;
    	}
    	invf[n]=fpow(f[n],mod-2);
    	for(int i=n-1;i>=0;--i){
    		invf[i]=invf[i+1]*(i+1)%mod;
    	}
    }
    
    
    ll C(int n,int k){
    	if(k<0 || k>n) return 0;
    	return f[n]*invf[k]%mod*invf[n-k]%mod;
    }
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        cin>>n>>x>>pos;
        init(n);
    
        int l=0,r=n;
        int L=0,R=0;
        while(l<r){
            int mid=(l+r)>>1;
            if(mid<=pos){
                if(mid!=pos) L++;
                l=mid+1;
            }
            else R++,r=mid;
        }
    
        fac[0]=1;
        for(int i=1;i<=n;++i){
            fac[i]=fac[i-1]%mod*i%mod;
        }
    
        cout<<C(x-1,L)%mod*fac[L]%mod*C(n-x,R)%mod*fac[R]%mod*fac[n-L-R-1]%mod<<endl;
    
        return 0;
    }