• 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 }
  • 相关阅读:
    如何显示Mac中文件的路径(path)
    什么样的音符对听起来悦耳?
    如何用iMovie剪辑视频
    【转】基因的故事
    4阶魔方解决方案
    SQ1魔方解决方案
    如何将Wikipedia链接的Unicode编码转成百分号编码
    我喜欢的LaTex编辑器
    react(redux)
    React (高阶组件)
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/7887743.html
Copyright © 2020-2023  润新知