• EOJ 1046 4个数的和为0


    poj 2785 http://poj.org/problem?id=2785

    eoj 1046 http://acm.cs.ecnu.edu.cn/problem.php?problemid=1046

        思路: 散列(hash) + 拉链法去冲突;

        具体过程:
        
        把num[][1-4]按列划分为num[][1-2] 和 num[][3-4];
        
        对    MAXN + num[i][1] + num[j][2]    散列;O(n^2 * len)

        对    MAXN - num[i][3] - num[j][4]    查找;O(n^2 * len)
        
        须使得被散列值为正,故用一大数 MAXN 保护;len为链表平均长度;

        注意:
        
        1.散列时,sum的地址由 hash(sum) = sum % MOD; 给出

        2.MOD取一个大素数的动机是:使得平均查找效率更优;

        也即散列得更均匀;

        3.解决冲突的链表,这里用数组模拟,貌似比malloc快。

        困惑:
            按题意,节点总数最多为 4000*4000,
            
            而我这里只开了NE个节点,觉得不够, 开大了又MLE。。。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define MAXN (1<<29)
     4 #define N 4005
     5 #define MOD 3999971
     6 #define NE 3999999
     7 typedef struct
     8 {
     9     int n;
    10     int cnt;
    11     int next;
    12 }E;
    13 int ie;
    14 E edge[NE];    //待分配的节点
    15 
    16 int num[N][5];
    17 int hash[MOD+5];
    18 
    19  
    20 void init()
    21 {
    22     for(int i=0; i<=MOD; i++)
    23         hash[i] = 0;        
    24     ie = 1;
    25 }
    26 int search(int n)
    27 {
    28     int a = n%MOD;
    29     int p = hash[a];
    30     while(p)
    31     {
    32         if(edge[p].n == n)
    33             return p;
    34         p = edge[p].next;
    35     }
    36     return 0;    //未找到
    37 }
    38  
    39 void add(int n)
    40 {
    41     int a = n%MOD;
    42     int p;
    43     if(p = search(n))    //找到,则仅将次数++
    44         edge[p].cnt ++;
    45             
    46     else        //未找到,则申请新节点,并插在头部。
    47     {
    48         edge[ie].n = n;
    49         edge[ie].cnt = 1;
    50         
    51         edge[ie].next = hash[a];
    52         hash[a] = ie++;
    53     }
    54  
    55 }
    56  
    57 int main()
    58 {
    59     int n;
    60     while(scanf("%d", &n) != EOF)
    61     {
    62         int i, j, cnt = 0;
    63         for(i=1; i<=n; i++)
    64             for(j=1; j<=4; j++)
    65                 scanf("%d", &num[i][j]);
    66         
    67         init();
    68         
    69         for(i=1; i<=n; i++)
    70             for(j=1; j<=n; j++)        
    71                add(MAXN + num[i][1] + num[j][2]);
    72         
    73         for(i=1; i<=n; i++)
    74             for(j=1; j<=n; j++)
    75             {
    76                 int p = search(MAXN - num[i][3] - num[j][4]);
    77                 if(p)
    78                     cnt += edge[p].cnt;
    79             }                    
    80         
    81         printf("%d\n", cnt);
    82     }
    83     
    84 }
    View Code
  • 相关阅读:
    聊聊高并发(二十)解析java.util.concurrent各个组件(二) 12个原子变量相关类
    windows curl ssl版本号编译
    扩展MSEG 加入Z字段
    HDU 1565 1569 方格取数(最大点权独立集)
    Codeforces Round #277.5 (Div. 2)
    葡萄城公布新版ActiveReports 9报表控件和报表server
    we标签
    ADO.NET (二)—— ADO和ADO .NET对照
    补:小玩文件2--将文本文件里的全部行加上行号后写到新文件里
    poj3061 Subsequence ,尺取法
  • 原文地址:https://www.cnblogs.com/KimKyeYu/p/3128801.html
Copyright © 2020-2023  润新知