您的位置:首页 > 其它

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

2017-05-21 21:39 399 查看

题目概述

给出一个方程:



其中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;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: