【浅谈折半搜索】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; };
相关文章推荐
- poj 1186 方程的解数【折半dfs+hash】
- poj 1186 方程的解数 折半枚举+hash
- 【暴力搜索】[POJ 1186]方程的解数
- POJ1186 方程的解数
- 【POJ 2785 4 Values whose Sum is 0】+ 折半枚举(双项搜索))
- POJ 2785 4 Values whose Sum is 0 折半枚举(双向搜索)
- poj 1186解方程(为什么双搜+hash)
- poj 1186 方程的解数 (hash+双向dfs)
- poj 1186 方程的解数(HASH,DFS)
- POJ 3977 Subset | 折半搜索
- poj 1186 poj 1840 方程的解数 hash+枚举 (n/2)
- poj 2785 4 Values whose Sum is 0(折半枚举(双向搜索))
- 折半搜索+hash——CODEVS1735 [NOI2001]方程的解数
- poj 1186 方程的解数
- POJ 1186 方程的解数 [解题报告] Java
- POJ 2785 4 Values whose Sum is 0【双向搜索/折半枚举】
- poj 1186 方程的解数(线性探测再哈希)
- POJ 1186 方程的解数 中文
- poj 1186:方程的解数
- poj 3977 折半枚举二分搜索