zoukankan      html  css  js  c++  java
  • 【CF1436C】Binary Search 题解

    原题链接

    题意简介

    要求有多少种 n 的排列,能够通过二分法正确地找到放在 pos 处的数字 x。
    答案对 1e9+7 取模。n<=1000。

    采用的二分法如下图:

    思路分析

    首先,这个排列中有一个位置是固定的,就是 a[pos] = x 。

    我们知道,二分查找的过程是不断缩小区间的过程,想要找到一个已经确定放在 pos 位置上的 x ,需要判断的 mid 的位置,需要的大于 x 的数的个数 c1 和小于 x 的数的个数 c0 也是固定的。

    也就是说,我们只需要模拟这个二分过程,求解出 c0 和 c1,然后利用排列组合的公式去计算就行了。

    (Ans = A^{c0}_{x-1} imes A^{c1}_{n-x} imes (n-1-c0-c1)!)

    由于本题的 n 的范围较小,可以不写逆元,直接暴力求阶乘。

    顺带一提,本题有一个坑点在于不一定有解。显然的,当小于 x 的数不够 c0 个或大于 x 的数不够 c1 个时无解。

    代码库

    #include <cstdio>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define Rep(i,a,b) for(int i=a;i>=b;i--)
    typedef long long ll;
    const int MOD=1e9+7,N=1002;
    inline ll _pow(ll x,ll p){
        ll ans=1;
        while(p){
            if(p&1) ans=ans*x%MOD;
            p>>=1; x=x*x%MOD;
        }
        return ans;
    }
    int n,x,pos,c0,c1;
    ll fact[N];
    int main(){
        scanf("%d%d%d",&n,&x,&pos);
        int l=0,r=n,mid;
        while(l<r){
            mid=(l+r)>>1;
            if(mid<pos) c0++,l=mid+1;
            else if(mid==pos) l=mid+1;
            else c1++,r=mid;
        }
        fact[0]=1;
        rep(i,1,n) fact[i]=(fact[i-1]*i)%MOD;
        if(x-1-c0<0||n-x-c1<0||n-1-c0-c1<0) printf("0
    ");
        else printf("%lld
    ",fact[x-1]*_pow(fact[x-1-c0],MOD-2)%MOD*fact[n-x]%MOD*_pow(fact[n-x-c1],MOD-2)%MOD*fact[n-1-c0-c1]%MOD);
        return 0;
    }
    

    END

  • 相关阅读:
    在SQLite中使用索引优化查询速度
    SQLite支持的SQL数据操作
    left (outer) join , right (outer) join, full (outer) join, (inner) join, cross join 区别
    深入理解Android内存管理原理(六)
    Merge Sorted Array
    Sort Colors
    Construct Binary Tree from Preorder and Inorder Traversal
    Binary Tree Postorder Traversal
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/Qing-LKY/p/CF1436C-solution.html
Copyright © 2011-2022 走看看