# 10月26日 CF#678 (Div. 2)强化训练 C_Binary Search

C_Binary Search

题目链接在此!

C. Binary Search
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
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 𝑥 in an array. For an array 𝑎 indexed from zero, and an integer 𝑥 the pseudocode of the algorithm is as follows:
在这里插入图片描述
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 𝑥!

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

Help Andrey and find the number of permutations of size 𝑛 which
contain 𝑥 at position 𝑝𝑜𝑠 and for which the given implementation
of the binary search algorithm finds 𝑥 (returns true). As the result
may be extremely large, print the remainder of its division by 109+7.

Input The only line of input contains integers 𝑛, 𝑥 and 𝑝𝑜𝑠
(1≤𝑥≤𝑛≤1000, 0≤𝑝𝑜𝑠≤𝑛−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 109+7.

Examples inputCopy 4 1 2 outputCopy 6 inputCopy 123 42 24 outputCopy
824071958 Note All possible permutations in the first test case:
(2,3,1,4), (2,4,1,3), (3,2,1,4), (3,4,1,2), (4,2,1,3), (4,3,1,2).

大概题意:

输入n,x,pos.(n表示全排列长度,x在数组pos位置上(从0开始))问多少个排列满足经过以下代码能输出为真:

思路分析:

二分;因为题目已经告诉a[mid]=x,也就是已经知道了left的值,根据left逆推出对于不同区间的a[middle]与x的关系。只有a[middle] <= x或者a[middle] > x这两种情况。使用组合数计算出答案。
注意题面的二分做法与实际的二分板子不同。

根据上面的代码模拟就好,mid<=pos,则l=mid+1,if(mid<pos) v[mid]=-1(即应该小于x)。否则v[mid]=1.
然后就是一个组合数,统计v为1的数为z,-1为f。c=n-z-f-1;

代码在此:

#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <iomanip>
#include <cmath>
#include <map>
#include <stack>
#include <algorithm>
#include <queue>
#include <set>
#include <cstdio>

typedef long long ll;
const int N = 1e3 + 7;
using namespace std;

const ll mod = 1e9 + 7;
int n, x, pos;
int a[N];
ll f[N];


ll qpow(ll xx,ll yy)
{
    ll res = 1;
    while(yy)
    {
        if(yy & 1) res = (res * xx) % mod;
        xx = (xx * xx) % mod;
        yy >>= 1;
    }
    return res % mod;
}

ll solve (int n,int m)
{
    return f[n] * qpow(f[n - m] % mod, mod - 2) % mod;
}

int main()
{
    f[0] = 1;
    for(int i=1;i<=1000;i++) f[i] = i * f[i - 1] % mod;
    scanf("%d%d%d",&n,&x,&pos);
    for(int i=0;i<n;i++)
        a[i] = i + 1;

    int smaller = 0;
    int bigger = 0;
    int l = 0;
    int r = n;
    while(l < r)
    {
        int mid = (l + r) / 2;
        if(a[mid] <= pos + 1)
        {
            l = mid + 1;
            smaller++;
        }
        else
        {
            r = mid;
            bigger++;
        }
    }
    int els = n - smaller - bigger;
    int B = n - x;
    int S = x;
    ll ans = solve(B, bigger) * solve(S - 1, smaller - 1) % mod * f[els] % mod;
    printf("%lld\n",ans);
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值