方程的解数
Time Limit: 15000MS | Memory Limit: 128000K | |
Total Submissions: 6393 | Accepted: 2198 | |
Case Time Limit: 5000MS |
Description
已知一个n元高次方程:
其中:x1, x2,...,xn是未知数,k1,k2,...,kn是系数,p1,p2,...pn是指数。且方程中的所有数均为整数。
假设未知数1 <= xi <= M, i=1,,,n,求这个方程的整数解的个数。
1 <= n <= 6;1 <= M <= 150。
方程的整数解的个数小于2 31。
★本题中,指数Pi(i=1,2,...,n)均为正整数。

其中:x1, x2,...,xn是未知数,k1,k2,...,kn是系数,p1,p2,...pn是指数。且方程中的所有数均为整数。
假设未知数1 <= xi <= M, i=1,,,n,求这个方程的整数解的个数。
1 <= n <= 6;1 <= M <= 150。

方程的整数解的个数小于2 31。
★本题中,指数Pi(i=1,2,...,n)均为正整数。
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
Source
初学hash做的第一道题,基本是照搬别人的程序。。。。。。看了一遍,自己敲了一遍,发现这是最普通的那种开放寻址加线性探查,然后期间用官方的pow函数死活不过,于是最后妥协了自己写的。。。。。
就是把算式剖开两半,然后对前面三个的结果做hash,之后对后面三个的结果的取反找hash,然后如果加起来是0那就是解。。感觉这个方法比较好,所以也记录一下。
#include <iostream>
#include<algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define MAX 4444444
using namespace std;
void left_ser(int d, int s);
void right_ser(int d, int s);
void insert_hash(int s);
int Hash(int s);
int getpow(int x, int p);
struct HASH{
int val;
int c;
}hash_t[MAX];
int use[MAX] = {0};
int mid, n, m, ans;
int k[11], p[11];
int main()
{
int i;
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// for (i = 0;i < MAX;i ++)
// hash_t[i].c = 0;
scanf("%d", &n);
scanf("%d", &m);
for (i = 0;i < n;i ++){
scanf("%d%d", &k[i], &p[i]);
}
ans = 0;
mid = n >> 1;
left_ser(0, 0);
right_ser(mid, 0);
printf("%d\n", ans);
return 0;
}
void left_ser(int d, int s){
int i;
if (d == mid){
insert_hash(s);
return;
}
for (i = 1;i <= m;i ++){
left_ser(d+1, s + k[d]*getpow(i, p[d]));
}
}
void right_ser(int d, int s){
int pos, i;
if (d == n){
s = -s;
pos = Hash(s);
if (hash_t[pos].val == s){
ans += hash_t[pos].c;
}
return;
}
for (i = 1;i <= m;i ++){
right_ser(d + 1, s + k[d]*getpow(i, p[d]));
}
}
void insert_hash(int s){
int pos = Hash(s);
hash_t[pos].val = s;
hash_t[pos].c++;
use[pos] = 1;
}
int Hash(int s){
int temp = s;
while (temp >= MAX) temp -= MAX;
while (temp < 0) temp += MAX;
while(use[temp] && hash_t[temp].val != s){
temp ++;
if (temp >= MAX){
temp -= MAX;
}
}
return temp;
}
int getpow(int x, int p) {
int tmp = 1;
while (p) {
if (p&1)
tmp *= x;
x *= x;
p >>= 1;
}
return tmp;
}