zoukankan      html  css  js  c++  java
  • Codeforces Round #678 (Div. 2) C. Binary Search(二分查找/思维/排列组合)

    C. Binary Search

    Andrey thinks he is truly a successful developer, but in reality he didn't know about the binary search algorithm until recently. After reading some literature Andrey understood that this algorithm allows to quickly find a certain number x in an array. For an array a indexed from zero, and an integer x the pseudocode of the algorithm is as follows:

    img

    Note that the elements of the array are indexed from zero, and the division is done in integers (rounding down).

    Andrey read that the algorithm only works if the array is sorted. However, he found this statement untrue, because there certainly exist unsorted arrays for which the algorithm find x!

    Andrey wants to write a letter to the book authors, but before doing that he must consider the permutations of size n such that the algorithm finds x in them. A permutation of size n is an array consisting of n distinct integers between 1 and n in arbitrary order.

    Help Andrey and find the number of permutations of size n which contain x at position pos and for which the given implementation of the binary search algorithm finds x (returns true). As the result may be extremely large, print the remainder of its division by 10^9+7.

    Input

    The only line of input contains integers n, x and pos (1≤x≤n≤1000, 0≤pos≤n−1) — the required length of the permutation, the number to search, and the required position of that number, respectively.

    Output

    Print a single number — the remainder of the division of the number of valid permutations by 10^9+7.

    Examples

    input

    Copy

    4 1 2
    

    output

    Copy

    6
    

    input

    Copy

    123 42 24
    

    output

    Copy

    824071958
    

    大意是构造一个1~n的排列,其中x在pos位置,使得题给的二分查找程序能正确找到x。问一共能构造出多少个这样的排列。

    思维题。首先想一下二分查找的过程,如果我们知道了x的位置pos,实际上就能确定出来需要找几次了,因为二分查找的前提是满足序列单调性,虽然排列不是单调的,但这个排列的下标是单调的(即1 2 3 4...n),不管是按什么二分,折返点的位置是固定的,因此我们直接对下标pos二分查找,在这个过程中记录比pos大的下标的个数以及比pos小的下标的个数,这实际上也就是在最终要构造出来的序列中二分转折点上比x大的数的个数以及比x小的数的个数。个数确定后就是排列组合问题了,对于这两部分先选再排,剩下的数求全排列,把这些乘起来即可。

    注意取模问题,组合数取模要套板子,以及二分查找的左端点是0 QAQ

    #include <iostream>
    #define ll long long 
    using namespace std;
    const int p = 1e9+7;
    ll inv(ll a)
    {
        return a==1?1:(ll)(p-p/a)*inv(p%a)%p;
    }
    ll C(ll n,ll m)//组合数快速取模 
    {
        if(m<0)return 0;
        if(n<m)return 0;
        if(m>n-m)m=n-m;
        ll up=1,down=1;
        ll i;
        for(i=0;i<m;i++)
        {
            up=up*(n-i)%p;
            down=down*(i+1)%p;
        }
        return up*inv(down)%p;
    }
    ll A(ll n, ll m)
    {
    	ll ans = 1;
    	for(ll i = n; i >= n - m + 1; i--)
    	{
    		ans = (ans * i) % p;
    	}
    	return ans;
    }
    int main()
    {
    	//freopen("data.txt", "r", stdin);
    	int n, x, pos;
    	cin >> n >> x >> pos;
    	int l = 0, r = n, mid = 0;
    	ll smaller = 0, bigger = 0;
    	while(l < r)
    	{
    		mid = (l + r) >> 1;
    		if(mid > pos)
    		{
    			r = mid;
    			bigger++;
    		}
    		else 
    		{
    			l = mid + 1;
    			if(mid < pos) smaller++;
    		}
    	}
    	//cout << bigger << ' ' << smaller << endl;
    	cout << C(n - x, bigger) * A(bigger, bigger) % p * C(x - 1, smaller) % p * A(smaller, smaller) % p * A(1ll * n - bigger - smaller - 1, 1ll * n - bigger - smaller - 1) % p << endl;
    	return 0;
    }
    
  • 相关阅读:
    设计模式之适配器模式(Decorator)
    可复用面向对象软件的基础
    dpkg命令的用法
    UML类图几种关系的总结
    Java多线程并发编程之原子变量与非阻塞同步机制
    Java内部类总结
    多线程并发编程之构建自定义同步工具
    多线程并发编程之显示锁ReentrantLock和读写锁
    多线程并发编程之变量
    汇编语言学习系列 冒泡排序实现
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13871775.html
Copyright © 2011-2022 走看看