方程的解数(difficult)
Time Limit:10000MS Memory Limit:65536K
Description
Input
第1行包含一个整数n。第2行包含一个整数M。第3行到第n+2行,每行包含两个整数,分别表示ki和pi。两个整数之间用一个空格隔开。第3行的数据对应i=1,第n+2行的数据对应i=n。
Output
仅一行,包含一个整数,表示方程的整数解的个数。
Sample Input
3
150
1 2
-1 2
1 2
Sample Output
178
分析:
用普通的枚举法是行不通的 会爆
所以我们只需枚举后三个数 前三个数的值S可以确定
判断后三个数的值是否等于-S即可 移项
并查集记录
CODE:
#include<cstdio>
#include<iostream>
#define p 4000037
using namespace std;
int g[p][2],a[7],b[7],n,m,mid; //a是系数 b是指数 g[i][0]是当前数字 g[i][1]是次数
long long ans;
int abs(int x){
return x<0?-x:x;
}
int ksm(int x,int y){ //快速幂 用cmath的pow不知为啥不行(可能我太弱了不会)
int ans=1;
while(y)
{
if(y&1) ans*=x;
x*=x;
y>>=1;
}
return ans;
}
int hash(int a)
{
return a%p;
}
void ifif(){ //特判
if(n==1)
if(!a[1]) printf("%d\n",m);
else cout<<"0";
}
int find(int x)
{
int y=hash(abs(x)),i=0; //查找hash中x的位置
while(i<p&&g[(i+y)%p][0]&&g[(i+y)%p][0]!=x)
i++;
return (i+y)%p;
}
int in(int x)
{
int y=find(x); //放入hash
g[y][0]=x;
g[y][1]++;
}
bool check(int x) //判断是否在hash内
{
return g[find(x)][0]==x;
}
void dfs1(int dep,int sum) //前半段的dfs
{
if(dep==mid)
for(int i=1;i<=m;i++)
in(sum+a[dep]*ksm(i,b[dep])); //全放入hash
else
for(int i=1;i<=m;i++)
dfs1(dep+1,sum+a[dep]*ksm(i,b[dep])); //继续搜
}
void dfs2(int dep,int sum) //搜后半段
{
if(dep==n)
for(int i=1;i<=m;i++)
{
long long t=-1*(sum+a[dep]*ksm(i,b[dep])); //移项
if(check(t)) ans+=g[find(t)][1]; //在hash中就累加答案
}
else
for(int i=1;i<=m;i++)
dfs2(dep+1,sum+a[dep]*ksm(i,b[dep])); //继续搜
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);mid=n>>1;
ifif();
if(n!=1)
{
dfs1(1,0);
dfs2(mid+1,0);
printf("%lld",ans);
}
}