Problem F: 等式
Submit: 104 Solved: 22
[Submit][Status][Web Board]
Description
Input
Output
Sample Input
Sample Output
题解:
a1*x13+a2*x23+a3*x33+a4*x43+a5*x53 = 0
<==> a1*x13+a2*x23+a3*x33 = -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 }