Problem F: 等式

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 104  Solved: 22
[Submit][Status][Web Board]

Description

Input

Output

Sample Input

37 29 41 43 47

Sample Output

654

题解: 

            a1*x13+a2*x23+a3*x33+a4*x43+a5*x5= 0

   <==> a1*x13+a2*x23+a3*x3= -1*(a4*x43+a5*x53)

  可以想办法利用三重循环枚举x1,x2,x3,算出a1*x1^3+a2*x2^3+a3*x^3得到的所有的100*100*100个值,先储存起来,假设存在a[ ]数组里。然后利用两重循环枚举x4,x5,逐个算出-1*(a4*x4^3+a5*x5^3)的所有值,如果这个值也存在于a[ ]中,就代表找到一组可行解,答案+1。

       现在的问题就变成了如何快速的查找a[ ]中的值,如果从头到尾扫一遍,那时间复杂度和直接五重循环枚举没有什么区别。

       这个问题可以用哈希表优化,先不解释哈希表是什么。先考虑如下问题:

       如果要存储和查找线性表(1,75,324,43,1353,90,46),有两种基本的思路:一种是定义一个数组A[10],把它们依次存入,但是这会给查找操作带来O(n)的时间复杂度,当数字非常多时,效率也许不可接受;第二种方法是定义数组A[2000],把这几个数字作为下标,即A[1]=1,A[75]=1,A[324]=1,A[43]=1,A[1353]=1,A[90]=1,A[46]=1,这样查找有没有x时只需判断A[x]是否等于1就可以了时间复杂度O(1),但是这种方法的问题也很大,就是空间浪费多,空间复杂度高。

  现在考虑优化第二种方法,假设我们设计函数h(x) = x mod 1235789 ,把原来的A[x]=1的操作变成A[ h(x) ] = 1 ,这样一来把数组大小设置为1235789就可以了。这样做也存在一定的问题: a != b 但 h(a) = h(b) = val 的情况是肯定存在的。问题也好解决,假设有m个数的h( )值都等于val,不妨把这m个值都用邻接表存起来(大致相当于A数组变成二维数组,只是第二维长度不定,m个数都存在A[ val ][ ]里 ),当要找q在不在A里时,就在A[ h(q) ][ ]里找,这个查找量比在所有数字中找要小的太多太多了,因为第二维会很短,毕竟h(a)=h(b)的情况并不多。

  看懂了上述问题及分析也就知道了这个题怎么做,a1*x1^3+a2*x2^3+a3*x^3得到的所有的100*100*100个值就相当于上面1,75,324那7个值,逐个算出的 -1*(a4*x4^3+a5*x5^3)的所有值就相当于要查找的q,把答案统计出来即可。

  注意:负数取模存在问题,而a1*x1^3+a2*x2^3+a3*x^3 与 (a4*x4^3+a5*x5^3)要想成为一组解,肯定互为相反数,不妨用unsigned long long 或 unsigned int类型再取模。 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 typedef unsigned long long ULL;
 8 const int mod = 1235789;
 9 struct A {
10     ULL val;
11     int next;
12 }a[2000000];
13 int cnt, head[mod];
14 int a1, a2, a3, a4, a5, a6, ANS;
15 inline ULL calc(int x,int y) {
16     return x*y*y*y;
17 }
18 inline void insert(int x, int y, int z) {
19     ULL tmp1 = calc(a1, x) + calc(a2, y) + calc(a3, z);
20     int tmp2 = int(tmp1 % (ULL)mod);
21     a[++cnt].val = tmp1;
22     a[cnt].next = head[tmp2];
23     head[tmp2] = cnt;
24 }
25 inline int ser(int x, int y) {
26     ULL tmp1 = -1 * (calc(a4, x) + calc(a5, y));
27     int tmp2 = int(tmp1 % (ULL)mod);
28     int ans = 0;
29     for (int i = head[tmp2]; i != -1; i = a[i].next) {
30         if (a[i].val == tmp1) ans++;
31     }
32     return ans;
33 }
34 int main() {
35     while (cin >> a1 >> a2 >> a3 >> a4 >> a5) {
36         cnt = 0;
37         for (int i = 0; i < mod; i++) head[i] = -1;
38         for (int i = -50; i <= 50; i++) {
39             for (int j = -50; j <= 50; j++) {
40                 for (int k = -50; k <= 50; k++) {
41                     if (i != 0 && j != 0 && k != 0) {
42                         insert(i, j, k);
43                     }
44                 }
45             }
46         }
47         ANS = 0;
48         for (int i = -50; i <= 50; i++) {
49             for (int j = -50; j <= 50; j++) {
50                 if (i != 0 && j != 0) {
51                     ANS += ser(i, j);
52                 }
53             }
54         }
55         cout << ANS << endl;
56     }
57     return 0;
58 }

 

posted @ 2017-11-24 00:23  CXCXCXC  阅读(339)  评论(0编辑  收藏  举报