[Hash]方程的解数

题目描述

在这里插入图片描述
约束条件
1<=n<=6;1<=M<=150
在这里插入图片描述
方程的整数解的个数小于231
★本题中,指数Pi(i=1,2,……,n)均为正整数。

题目解析

最简单的思路是穷举所有未知数的取值,这样时间复杂度是 O(Mn) ,显然会超时

注意到M的范围,若想不超时,似乎算法的复杂度上限应该是 O(M3) 左右,这是因为 1503 < 107

所以通过枚举前一半式子的值S和后一半式子的值是否等于-S(移项)

到这,就是解决如何迅速找到某个S值是否出现过,以及出现的次数

于是想到用哈希表解决,然而有一点需要注意,不仅需要纪录某个S是否出现,还要出现的次数,所以可以用一个二维数组,加一个存储出现次数的即可。

代码

#include<iostream>
#include<string>
#include<cmath>
#define p 4000037//质数 
#define h(x) x%p
#define LL long long
using namespace std;
LL n,m,mid,ans;
int k[10],b[10],a[p+5][2];
//a[x][0] 记录哈希函数值为x的S值,a[x][2] 记录这个 S 值出现了几次
LL qp(LL x,int y)
{
	LL sum=1;
	while(y)
	{
	  if(y&1) sum*=x;
	  x*=x;
	  y>>=1;
	}
	return sum;
}//快速幂 
int loc(int x)
{
	int k=h(abs(x)),i=0;
	while(i<p&&a[(k+i)%p][0]!=x&&a[(k+i)%p][0]!=0)
	 i++;
	return (k+i)%p;
}//查找关键字在哈希表的位置 
void dfs1(int lev,LL sum)//搜前半段 
{
	if(lev>mid)
	{
	  //将sum加进哈希表
	  int ss=loc(sum);
	  a[ss][1]++;//次数+1 
	  a[ss][0]=sum;//存进去 
	  return;
	}
	for(int i=1;i<=m;i++)
	 dfs1(lev+1,sum+k[lev]*qp(i,b[lev]));
}
void dfs2(int lev,LL sum)//搜后半段 
{
	if(lev>n)
	{
	  long long t=-1*sum;//移项变号 
	  int ss=loc(t);
	  if(a[ss][0]==t) //若相等,则加上出现次数 
	   ans+=a[ss][1]; 
	  return;
	}
	for(int i=1;i<=m;i++)
	 dfs2(lev+1,sum+k[lev]*qp(i,b[lev]));
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	 cin>>k[i]>>b[i];
	mid=n/2;
	if(n==1)
	{
	 if(!a[1]) cout<<m;
	 else cout<<"0";
	 return 0;
	}//特判 
	dfs1(1,0);
	dfs2(mid+1,0);
	cout<<ans;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值