您的位置:首页 > 其它

poj1186——方程的解数

2017-12-05 10:43 316 查看
题目大意:

,1 <= xi <= M, i=1...n(1 <= n <= 6;1 <= M <= 150)

输入:n

           M

           ki  pi(共n行)

输出:整数解的个数

分析:折半搜索+哈希。暴力枚举超时,所以将方程分成两半,先枚举前一半的解,将总值哈希存储,然后枚举后一半看看是否和左值相等,若是则是一个解。

代码:转载自http://blog.csdn.net/sepnine/article/details/50154181

#include <iostream>  

using namespace std;  

const int HASHLEN=1000023;  

const int MAXNODENUM=4000024;  

int n,m,ans,e,tag;  

int k[32],p[32];  

int head[HASHLEN+10];  

  

struct Node{  

    int val,cnt,nxt;  

}edge[MAXNODENUM+10];   

  

int hash_value(int x)  

{  

    return x>0?x%HASHLEN:x%HASHLEN+HASHLEN;    

}  

  

void insert(int x)  

{  

    int y=hash_value(x);      

    for(int i=head[y];i!=-1;i=edge[i].nxt){  

        if(edge[i].val==x){  

            ++edge[i].cnt;  

            return ;  

        }  

    }  

    edge[e].val=x,edge[e].cnt=1,edge[e].nxt=head[y],head[y]=e++;  

}  

  

int lookup(int x)  

{  

    int y=hash_value(x);      

    for(int i=head[y];i!=-1;i=edge[i].nxt)  

        if(edge[i].val==x)  

            return edge[i].cnt;  

    return 0;  

}  

  

void dfs(int cur,int end,int sum)  

{  

    if(cur==end){  

        if(tag==0)  

            insert(sum);  

        else  

            ans+=lookup(-sum);  

        return ;          

    }  

    for(int i=1;i<=m;++i){  

        int t=1;  

        for(int j=0;j<p[cur];++j)  

            t*=i;  

        dfs(cur+1,end,sum+k[cur]*t);  

    }                 

}  

  

int main()  

{  

    memset(head,-1,sizeof(head));
 //哈希邻接表的头结点

    ans=e=0;  //e为哈希邻接表中边结点个数

    scanf("%d%d",&n,&m);  

    for(int i=0;i<n;++i)  

        scanf("%d%d",&k[i],&p[i]);  

    tag=0;  

    dfs(0,n/2,0);  

    tag=1;  

    dfs(n/2,n,0);  

    printf("%d",ans);     

    return 0;     

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: