[NOI2001]方程的解数
题目
DFS(meet in the middle)
通过此条件剪枝,由于本题数据较大,可通过HASH表存储方案数。
#include<cstdio>
#include<vector>
#include<cmath>
#include<cstdlib>
using namespace std;
#define MAXN 6
#define MAXH 4999999
struct node{
int pos,cnt;
node *next;
}*adj[MAXH+10];
void addnode(int pos){
node *p=new node;
p->pos=pos;
p->cnt=1;
p->next=adj[abs(pos%MAXH)];
adj[abs(pos%MAXH)]=p;
}
int n,m,k[MAXN+2],p[MAXN+2],mid,ans,mypow[160][10];
void read(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&k[i],&p[i]);
}
void dfs1(int i,int sum){
if(i>mid){
int h=abs(sum%MAXH);
node *p;
for(p=adj[h];p;p=p->next)
if(p->pos==sum){
p->cnt++;
break;
}
if(!p)
addnode(sum);
return;
}
for(int x=1;x<=m;x++){
long long t=sum+k[i]*(long long)mypow[x][i];
if(abs(t)>0x7f7f7f7f)
break;
dfs1(i+1,(int)t);
}
}
void dfs2(int i,int sum){
if(i==mid){
int h=abs(sum%MAXH);
node *p;
for(p=adj[h];p;p=p->next)
if(p->pos==sum){
ans+=p->cnt;
break;
}
return;
}
for(int x=1;x<=m;x++){
long long t=sum-k[i]*(long long)mypow[x][i];
if(abs(t)>0x7f7f7f7f)
break;
dfs2(i-1,(int)t);
}
}
int main()
{
read();
int i,j;
for(i=1;i<=150;i++){
for(j=1;j<=n;j++)
mypow[i][j]=pow(i,p[j]);
}
mid=n/2;
dfs1(1,0);
dfs2(n,0);
printf("%d\n",ans);
}