题意:
思路:
我们可以把这个方程一半的加数移到右边去,例k1x1p1+k2x2p2+k3x3p3=0移项变成k1x1p1+k2x2p2=-k3x3p3可以减少我们枚举x的次数,用哈希表存左边求出的情况有哪些,在右边枚举的时候我们就可以判断是否和左边相等,然后加上次数就可以了。
代码:
#include<cstdio>
#define maxn 4000003
using namespace std;
int z,a[maxn][2],n,k[7],p[7],m,ans;
int ksm(int x,int y)//快速幂
{
int s=1;
while (y>0)
{
if (y%2!=0) s*=x;
x*=x;
y/=2;
}
return s;
}
int hash(int x)
{
if (x<0) x=x*-1;
return x%maxn;
}
int locate(int x)
{
int i=0,w=hash(x);
while (i<maxn&&a[(i+w)%maxn][0]!=0&&a[(i+w)%maxn][0]!=x) i++;
return (i+w)%maxn;
}
void insert(int x)
{
int z=locate(x);
a[z][0]=x;
a[z][1]++;//a[][1]存左边求出的结果的次数
}
void dfs(int x,int sum)
{
if (x==n/2)
for (int i=1;i<=m;i++)
insert(sum+k[x]*ksm(i,p[x]));//把我们求出的情况加到哈希表里去
else
for (int i=1;i<=m;i++)
dfs(x+1,sum+k[x]*ksm(i,p[x]));//继续枚举x
return;
}
void bfs(int x,int sum)
{
int t;
if (x==n)
for (int i=1;i<=m;i++)
{
t=-1*(sum+k[x]*ksm(i,p[x]));//因为右边的是移项了的,所以要变号
if (a[locate(t)][0]==t) ans+=a[locate(t)][1];//加上出现次数
}
else
for (int i=1;i<=m;i++)
bfs(x+1,sum+k[x]*ksm(i,p[x]));//枚举x
return;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d%d",&k[i],&p[i]);
if (n==1)//这里是特殊情况
{
if (k[1]==0) printf("%d",m);
else printf("0");
return 0;
}
dfs(1,0);//求左边的
bfs(n/2+1,0);//把这个方程分成两段求,这里求右边
printf("%d",ans);
}