现在的位置: 首页 > 综合 > 正文

二分搜索典例

2013年12月07日 ⁄ 综合 ⁄ 共 1937字 ⁄ 字号 评论关闭

题目:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=612

 

题意:给一个正整数n,n小于10^8,对于X^X达到n位时,求最小的X,注意是达到n。

 

分析:先求出第一个满足X^X的位数大于等于n位的X,然后从上到下枚举X,如果X^X的位数小于n时就break。那么i+1就是答案。

 

 

题目:http://codeforces.com/contest/325/problem/B

 

题意:给一个正整数n<=10^18,m是奇数,求的解有多少个,并按从小到大的顺序输出所有的

 

分析:方法就是枚举k,二分m。

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>

using namespace std;
typedef long long LL;
const int N = 1005;
const LL INF = 1e18;
const LL R = 3*1e9;

LL S[N];
int cnt;

void Binary_Search(LL n)
{
    for(int k=0;k<63;k++)
    {
        LL l = 1;
        LL r = R;
        if(k >= 30) r = INF >> k;
        while(l <= r)
        {
            LL m = (l + r) >> 1;
            LL ans = (((LL)1 << k) - 1) * m * 2 + m * (m - 1);
            if(ans > 2*n) r = m - 1;
            else if(ans < 2*n) l = m + 1;
            else
            {
                if(m&1) S[cnt++] = m * ((LL)1 << k);
                break;
            }
        }
    }
}

int main()
{
    LL n;
    cin>>n;
    cnt = 0;
    Binary_Search(n);
    sort(S,S+cnt);
    if(cnt == 0) puts("-1");
    else
    {
        for(int i=0;i<cnt;i++)
           cout<<S[i]<<endl;
    }
    return 0;
}

 

 

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4282

 

题意:对于方程X^Z + Y^Z + XYZ = K,已知K求此方程解的个数,其中要求X<Y,Z>1,而K的范围是0到2^31。

 

分析:这道题明显的二分搜索题。

 

首先我们来分析Z的范围:由于X,Y为正整数,X < Y,则1 < X < Y, =====>  Y >= 2

=>  X^Z + Y^Z + XYZ > Y^Z  

=>  2^Z <= Y^Z < 2^31

所以得到2 <= Z<31

对于Z=2时我们来特殊处理。所以只分析Z在3<=Z<31的情况。

我们再来分析X的范围:

对于方程X^Z + Y^Z + XYZ = K, X < Y,则有X^Z + Y^Z + XYZ > 2*X^Z + X*X*Z >= 2*X^3 + 3*X^2

即我们得到:2*X^3 + 3*X^2 < 2^31   解这个方程有:X < 1024

于是现在我们得到了3 <= Z < 31,1 <= X < 1024,当然Z=2特殊处理。接下来就直接枚举X,Z,来二分Y。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>

using namespace std;
typedef long long LL;

LL f[1300][32];

void Init()
{
    for(int i=1; i<1300; i++)
    {
        f[i][0] = 1;
        for(int j=1; j<31; j++)
        {
            f[i][j] = f[i][j-1] * i;
            if(f[i][j] > 2147483648LL)
                break;
        }
    }
}

bool Binary_Search(int x,int z,int K)
{
    int mid;
    int l=x+1;
    int r=1290;
    while(l <= r)
    {
        mid = (l + r) >> 1;
        if(f[mid][z] == 0)
        {
            r = mid - 1;
            continue;
        }
        LL ret = f[x][z] + f[mid][z] + x * mid * z;
        if(ret < K)
            l = mid + 1;
        else if(ret > K)
            r = mid - 1;
        else
            return true;
    }
    return false;
}

int main()
{
    Init();
    int K;
    while(~scanf("%d",&K),K)
    {
        LL ans = 0;
        int tmp = (int)sqrt(1.0*K);
        if(tmp*tmp == K)
        {
            if(tmp % 2)
                ans += tmp / 2;
            else
                ans += (tmp / 2 - 1);
        }
        for(int x=1; x<1024; x++)
        {
            for(int z=3; z<31; z++)
            {
                if(f[x][z] == 0) break;
                if(Binary_Search(x,z,K))
                    ans++;
            }
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

抱歉!评论已关闭.