POJ #1186 方程的解数 | 中途相遇法 + Hash | 解题报告
来源:互联网 发布:上海淘宝厂家 编辑:程序博客网 时间:2024/05/20 03:08
POJ #1186 - 方程的解数
时限 5000MS/Case 内存 128MB/Case
题目描述
已知一个n元高次方程:
其中:x1, x2,...,xn是未知数,k1,k2,...,kn是系数,p1,p2,...pn是指数。且方程中的所有数均为整数。
假设未知数1 <= xi <= M, i=1,,,n,求这个方程的整数解的个数。
1 <= n <= 6;1 <= M <= 150。
方程的整数解的个数小于231。
★本题中,指数Pi(i=1,2,...,n)均为正整数。
输入格式
第1行包含一个整数n。第2行包含一个整数M。第3行到第n+2行,每行包含两个整数,分别表示ki和pi。两个整数之间用一个空格隔开。第3行的数据对应i=1,第n+2行的数据对应i=n。
输出格式
仅一行,包含一个整数,表示方程的整数解的个数。
样例输入
31501 2-1 21 2
样例输出
178
1<=M<=150,1<=N<=6,1<=X[i]<=M
----------------------------------------------------------
题目分析
确定思路,因为这道题不好建立数学解题模型,所以直接选择上枚举算法。
枚举6个数再来检查的话时间复杂度为O(M^6),最坏时间复杂度为O(150^6),无法通过此题。
所以我们想到用中途相遇的思想,先枚举前3个数,把前三个数的和存起来,再枚举后三个数,得到的每一个和与前面的和进行验算,即可得到ans。
因为前半边最多能产生的和的个数为150*150*150,所以我们构建哈希表:hash[4000000]。
----------------------------------------------------------
代码(枚举过程挺渣的,好在1500ms跑完了全部测试点)
#include <iostream>#include <algorithm>#include <cstdio>#include <cstdlib>#include <cstring>#include <map>#include <set>#include <queue>#include <stack>#include <vector>#define hashsize 4000003using namespace std;long long p[151][10];struct node{int value;int count;};node h[hashsize];bool used[hashsize];int get_hash(int x){int tmp=(abs(x))%hashsize;while(used[tmp] && h[tmp].value!=x){tmp++;if(tmp>4000000) tmp%=hashsize;}return tmp;}int hash_count(int x){int i=get_hash(x);return h[i].count;}void hash_insert(int x){int i=get_hash(x);h[i].value=x;used[i]=true;h[i].count++;}int pow(int base,int power){if(p[base][power]>=1) return p[base][power];if(power==0) return 1;long long temp=pow(base,power/2);if(power%2==1) return p[base][power]=(temp*temp)*base;else return p[base][power]=(temp*temp);}void calcpow(){for(int i=1;i<=150;i++) p[i][1]=i;for(int i=1;i<=150;i++)for(int j=2;j<=9;j++) p[i][j]=p[i][j-1]*i;return;}void work(){int k[7],pow_up[7];int n,m,ans=0,tempr,cnt;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d%d",&k[i],&pow_up[i]);if(n==1){for(int i=1;i<=m;i++){if(pow(i,pow_up[1])*k[1]==0) ans++;}}else if(n==2){for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){if(pow(i,pow_up[1])*k[1]+pow(j,pow_up[2])*k[2]==0) ans++;}}}else if(n==3){for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){for(int l=1;l<=m;l++){if(pow(i,pow_up[1])*k[1]+pow(j,pow_up[2])*k[2]+pow(l,pow_up[3])*k[3]==0) ans++;}}}}else if(n==4){for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){hash_insert(pow(i,pow_up[1])*k[1]+pow(j,pow_up[2])*k[2]);}}for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){ans+=hash_count(-(pow(i,pow_up[3])*k[3]+pow(j,pow_up[4])*k[4]));}}}else if(n==5){for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){hash_insert(pow(i,pow_up[1])*k[1]+pow(j,pow_up[2])*k[2]);}}for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){for(int l=1;l<=m;l++){ans+=hash_count(-(pow(i,pow_up[4])*k[4]+pow(j,pow_up[5])*k[5]+pow(l,pow_up[3])*k[3]));}}}}else if(n==6){calcpow();for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){for(int l=1;l<=m;l++){hash_insert(p[i][pow_up[1]]*k[1]+p[j][pow_up[2]]*k[2]+p[l][pow_up[3]]*k[3]);}}}for(int i=1;i<=m;i++){for(int j=1;j<=m;j++){for(int l=1;l<=m;l++){ans+=hash_count(-(p[i][pow_up[4]]*k[4]+p[j][pow_up[5]]*k[5]+p[l][pow_up[6]]*k[6]));}}}}printf("%d",ans);return;}int main(){work();return 0;}
阅读全文
0 0
- POJ #1186 方程的解数 | 中途相遇法 + Hash | 解题报告
- POJ 1186 方程的解数 [解题报告] Java
- poj 1186 方程的解数 折半枚举+hash
- poj 1186 方程的解数(HASH,DFS)
- poj 1186 方程的解数 (hash+双向dfs)
- POJ 1186 方程的解数
- poj 1186 方程的解数
- poj 1186:方程的解数
- POJ 1186 方程的解数
- UVa 10125 - Sumsets 解题报告(中途相遇法)
- [DFS][hash]方程的解数
- poj 1903 中途相遇法
- 【暴力搜索】[POJ 1186]方程的解数
- POJ 1186 方程的解数 中文
- UVa 10125 - Sumsets (中途相遇法 hash)
- 1186 -- 方程的解数
- POJ P1186 方程的解数
- UVa 10318 Security Panel 解题报告(暴力,中途相遇法)
- 机器学习实战_初识kNN算法_理解其python代码
- PAT a1050题解
- ‘XXXX’ was compiled with optimization
- Matlab常用概率密度函数、累计概率分布函数及其逆函数
- Flink学习笔记 --- 研究 FlinkForward2017 源码
- POJ #1186 方程的解数 | 中途相遇法 + Hash | 解题报告
- PAT a1051题解
- PAT a1052题解
- 自定义表格控件
- 信号槽如何传递参数
- Nginx80端口转发+域名——实现IP+端口隐藏
- 第2章 渲染流水线
- PAT a1053题解
- 端口映射怎么设置