【浅谈折半搜索】POJ1186[方程的解数]题解

题目概述

给出一个方程:
这里写图片描述
其中p1是正整数,k1是整数,1<=x<=m。求方程整数解的个数。

解题报告

折半搜索是一个很常用的搜索方法,就是把要搜索的东西分成两半,其中这两半是可以互相独立的。

就上面那段话体现不出折半搜索的作用,我们来讲讲这道题。这道题如果直接搜索,肯定要超时的。但是我们发现这n个未知数可以分成两半:左边n/2个,右边n/2个。这样再搜索两边就不会超时了。而这两部分是可以互相独立的,只需要记录左边的值的可能个数,然后在处理右边的时候统计就行了。

示例程序

用map很慢,我用mapTLE了。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=6,maxt=3375000;

int n,m,K[maxn+5],P[maxn+5],num[maxt+5];
LL ans;

int power(int w,int b)
{
    int s=1;
    while (b) {if (b&1) s*=w;b>>=1;if (b) w*=w;}
    return s;
}
void Dfs1(int st,int gl,int now) //左边
{
    if (st>gl) {num[++num[0]]=now;return;}
    for (int i=1;i<=m;i++)
        Dfs1(st+1,gl,now+power(i,P[st])*K[st]);
}
int Find(int x) //用二分统计
{
    int L=1,R=num[0],l,r;
    while (L<=R)
    {
        int mid=L+(R-L>>1);
        if (x<=num[mid]) R=mid-1; else L=mid+1;
    }
    l=L;L=1;R=num[0];
    while (L<=R)
    {
        int mid=L+(R-L>>1);
        if (x>=num[mid]) L=mid+1; else R=mid-1;
    }
    r=R;
    return r-l+1;
}
void Dfs2(int st,int gl,int now) //右边
{
    if (st>gl) {ans+=Find(-now);return;}
    for (int i=1;i<=m;i++)
        Dfs2(st+1,gl,now+power(i,P[st])*K[st]);
}
int main()
{
    freopen("program.in","r",stdin);
    freopen("program.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d%d",&K[i],&P[i]);
    Dfs1(1,n/2,0);sort(num+1,num+1+num[0]);
    Dfs2(n/2+1,n,0);
    printf("%lld\n",ans);
    return 0;
};
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值