题目描述
约束条件
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;
}