【uva 1152】4 Values Whose Sum is Zero(算法效率--中途相遇法+Hash或STL库)
题意:给定4个N元素几个A,B,C,D,要求分别从中选取一个元素a,b,c,d使得a+b+c+d=0。问有多少种选法。(N≤4000,D≤2^28)
解法:首先我们从最直接最暴力的方法开始思考:四重循环O(n^4)枚举;三重循环枚举,把剩下的一个集合排序后二分查找,O(n^3 log n)。在进一步想,运用“中途相遇法”:从两个不同的方向来解决问题,最后“汇集”到一起的方法。(有类似于“双向广度优先搜索”的思想)通过两重循环枚举出A,B两个集合中的元素可组成的和,一般想到开个以和为值的数组记录个数。但是由于D值有2^28这么大,所以不行。于是——解决技巧很厉害!(。ì _ í 。)
实现1:既然不能将相同的数一个个竖向累积在一个数组位,那就可以把这些相同的数横向拉伸,排成一排。使用STL库头文件algorithm里的upper_bound和lower_bound函数直接查找到>d和>=d的数的位置,相减就是d值的数的个数。这样的时间复杂度是O(n^2 log n)。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5 #include<iostream>
6 using namespace std;
7
8 const int N=4010;
9 int a[N],b[N],c[N],d[N],sum[N*N];
10
11 int main()
12 {
13 int T;
14 scanf("%d",&T);
15 while (T--)
16 {
17 int n;
18 scanf("%d",&n);
19 for (int i=1;i<=n;i++)
20 scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
21 int m=0;
22 for (int i=1;i<=n;i++)
23 for (int j=1;j<=n;j++)
24 sum[++m]=a[i]+b[j];
25 sort(sum+1,sum+1+m);
26 long long cnt=0;//long long
27 for (int i=1;i<=n;i++)
28 for (int j=1;j<=n;j++)
29 cnt+=upper_bound(sum+1,sum+1+m,-c[i]-d[j])-lower_bound(sum+1,sum+1+m,-c[i]-d[j]);
30 printf("%lld\n",cnt);
31 if (T) printf("\n");
32 }
33 return 0;
34 }
STL库实现
实现2:当然检索的高效算法 Hash也是可以的。我这里用的是闭散列表储存,即%一个大整数(一般是质数)之后放在相应的位置。若该位置已存储了其他数,则将这个数一直往后推直到一个空的位置。由于和的个数最多为n^2,小于列表的长度足够存储,那么就算和的值很大也不影响了。
关于具体代码我再解释一些:1.常量的0x7fffff表示16进制的7fffff,f是15,即2^23;2.结构体哈希表重载了运算符[],这样就可以直接得到每个数的个数了;3.用&运算而不是%,可能是因为运算速度或存储空间,改成%就RE,但其实它们的意思是一样的,目的都是使数较集中的放在一起。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 using namespace std;
6
7 const int N=4010;
8 int a[N],b[N],c[N],d[N];
9
10 struct ha_map
11 {
12 static const int mod=0x7fffff;
13 int s[mod+1],d[mod+1];
14 void clear() {memset(s,0,sizeof(s));}
15 int& operator [] (int x)
16 {
17 int i;
18 for (i=x&mod;s[i]&&d[i]!=x;i=(i+1)&mod);
19 d[i]=x;
20 return s[i];
21 }
22 }ha;
23
24 int main()
25 {
26 int T;
27 scanf("%d",&T);
28 while (T--)
29 {
30 int n;
31 scanf("%d",&n);
32 for (int i=1;i<=n;i++)
33 scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
34 ha.clear();
35 for (int i=1;i<=n;i++)
36 for (int j=1;j<=n;j++)
37 ha[a[i]+b[j]]++;
38 long long cnt=0;//long long
39 for (int i=1;i<=n;i++)
40 for (int j=1;j<=n;j++)
41 cnt+=ha[-c[i]-d[j]];
42 printf("%lld\n",cnt);
43 if (T) printf("\n");
44 }
45 return 0;
46 }
Hash实现
Hash的速度是STL库的4倍多~~ (-ω-*)
【uva 1152】4 Values Whose Sum is Zero(算法效率--中途相遇法+Hash或STL库)的更多相关文章
- UVA 1152 4 Values whose Sum is 0 (枚举+中途相遇法)(+Java版)(Java手撕快排+二分)
4 Values whose Sum is 0 题目链接:https://cn.vjudge.net/problem/UVA-1152 ——每天在线,欢迎留言谈论. 题目大意: 给定4个n(1< ...
- uva 1152 4 values whose sum is zero ——yhx
The SUM problem can be formulated as follows: given four lists A;B;C;D of integer values, computehow ...
- UVa 1152 -4 Values whose Sum is 0—[哈希表实现]
The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute ...
- UVA - 1152 4 Values whose Sum is 0(中途相遇法)
题意:从四个集合各选一个数,使和等于0,问有多少种选法. 分析:求出来所有ai + bi,在里面找所有等于ci + di的个数. #pragma comment(linker, "/STAC ...
- UVa 1152 4 Values whose Sum is 0
题意:给出n,四个集合a,b,c,d每个集合分别有n个数,分别从a,b,c,d中选取一个数相加,问使得a+b+c+d=0的选法有多少种 看的紫书,先试着用hash写了一下, 是用hash[]记录下来a ...
- UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)
摘要:中途相遇.对比map,快排+二分查找,Hash效率. n是4000的级别,直接O(n^4)肯定超,所以中途相遇法,O(n^2)的时间枚举其中两个的和,O(n^2)的时间枚举其他两个的和的相反数, ...
- UVA - 1152 4 Values whose Sum is 0问题分解,二分查找
题目:点击打开题目链接 思路:暴力循环显然会超时,根据紫书提示,采取问题分解的方法,分成A+B与C+D,然后采取二分查找,复杂度降为O(n2logn) AC代码: #include <bits/ ...
- UVA - 1152 --- 4 Values whose Sum is 0(二分)
问题分析 首先枚举a和b, 把所有a+b记录下来放在一个有序数组,然后枚举c和d, 在有序数组中查一查-c-d共有多少个.注意这里不可以直接用二分算法的那个模板,因为那个模板只能查找是否有某个数,一旦 ...
- uva1152 - 4 Values whose Sum is 0(枚举,中途相遇法)
用中途相遇法的思想来解题.分别枚举两边,和直接暴力枚举四个数组比可以降低时间复杂度. 这里用到一个很实用的技巧: 求长度为n的有序数组a中的数k的个数num? num=upper_bound(a,a+ ...
随机推荐
- Redis 设计与实现 10:五大数据类型之有序集合
有序集合 sorted set (下面我们叫zset 吧) 有两种编码方式:压缩列表 ziplist 和跳表 skiplist. 编码一:ziplist zset 在 ziplist 中,成员(mem ...
- Python——绘制埃菲尔铁塔
from turtle import * import turtle colormode(255) #设置turtle颜色模式 speed(0) #速度 setup(800,800,720,0) #画 ...
- 【Oracle】修改列的大小
alter table 表名 modify column_name varchar2(32) alter table 表名 modify (column_name1 varchar(20) defa ...
- linux查看文件夹和磁盘内存及服务器对应的ip
多进程统计cpu 数目 n_cpu = multiprocessing.cpu_count() print(n_cpu) 查看文件夹占用磁盘空间 du -h --max-depth=1 /path 查 ...
- 关于BAPI_TRANSACTION_COMMIT一点说明
我们调用bapi做了相关的业务操作后,通常都要在后面调用 BAPI_TRANSACTION_COMMIT来提交所做得更改 然而,有时候,在程序中需要调用多个不同的BAPI实现不同的功能,那么这个时候就 ...
- dubbo快速入门demo
参考文章 https://blog.csdn.net/abcwanglinyong/article/details/81906027 该demo包含三个项目,分别是: 服务提供端项目:provider ...
- mysql(连接查询和数据库设计)
--创建学生表 create table students ( id int unsigned not null auto_increment primary key, name varchar(20 ...
- 现有以下关系型数据库中的表(见表4-20表4-21和表4-22),要求将具转换为适合Hbase存储的表并插入数据。
① createTable(String tableName, String[] fields) 创建表,参数tableName为表的名称,字符串数组fields为存储记录各个域名称的数组.要 求当H ...
- [从源码学设计] Flume 之 memory channel
[从源码学设计] Flume 之 memory channel 目录 [从源码学设计] Flume 之 memory channel 0x00 摘要 0x01 业务范畴 1.1 用途和特点 1.2 C ...
- 内存模型 Memory model 内存分布及程序运行中(BSS段、数据段、代码段、堆栈
C语言中内存分布及程序运行中(BSS段.数据段.代码段.堆栈) - 秦宝艳的个人页面 - 开源中国 https://my.oschina.net/pollybl1255/blog/140323 Mem ...