传送门:Problem 2785

题意:

  给定 n 行数,每行都有 4 个数A,B,C,D。

  要从每列中各抽取出一个数,问使四个数的和为0的所有方案数。

  相同数字不同位置当作不同数字对待。

题解:

  如果采用暴力的话,从4个数列中选择数组合,共有(N^4)种选择,故时间复杂度为O(N^4),指定会超时。

  但,如果将它们分成 AB,CD两组,每组只有 N^2 个组合,而 N 的数据范围为 N < 4000,故采用此种方法不会超时。

AC代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=+; int n;
int a[maxn*maxn];
int b[maxn*maxn];
int num[maxn][]; ll Solve()
{
int index=;
for(int i=;i <= n;++i)
for(int j=;j <= n;++j)
{
a[index]=num[i][]+num[j][];//存储所有的A+B的值
b[index]=num[i][]+num[j][];//存储所有的C+D的值
index++;
}
sort(a+,a+index);
sort(b+,b+index);
ll res=;
/**
A+B+C+D=0 -> C+D=-(A+B)
而C+D的所有值已经预处理好,故可通过二分查找存在于b[]中 -(A+B) 的个数即可
**/
for(int i=;i < index;++i)
{
int t=lower_bound(b+,b+index,-a[i])-b;
int k=;
while(t < index && b[t] == -a[i])//查找 -(A+B) 的个数
k++,t++;
res += k;
}
return res;
} int main()
{
while(~scanf("%d",&n))
{
for(int i=;i <= n;++i)
for(int j=;j <= ;++j)
scanf("%d",&num[i][j]);
printf("%lld\n",Solve());
}
return ;
}

最新文章

  1. iOS点击推送消息跳到应用指定页面
  2. 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
  3. nyoj 712 探 寻 宝 藏--最小费用最大流
  4. python学习笔记三 文件操作(基础篇)
  5. MSP430F149学习之路——时钟1
  6. 在telnet下操作memcache详解(操作命令详解)
  7. uva 11983 Weird Advertisement 扫描线
  8. 用Raphael在网页中画圆环进度条
  9. [HDU 2068] RPG的错排 (错排问题)
  10. insert 和 if x is not None
  11. sicily 1099 Packing Passengers
  12. 用C语言打印出三角函数
  13. 关于JavaScript的事件处理一些知识
  14. JAVA面对对象(四)——抽象类
  15. 五. Python基础(5)--语法
  16. “吃神么,买神么”的第一个Sprint计划(结束)
  17. JQuery-Dialog(弹出窗口,遮蔽窗口)
  18. php 值引用
  19. python---权限管理和菜单生成
  20. nginx缓存和flask_cache

热门文章

  1. php 中self,this的区别和实地操作
  2. 移动app rem
  3. 【Beta版本发布】爬虫队长装备全面更新!
  4. Maven+SSM整合.doc
  5. PHP文件系统操作常用函数
  6. ASP.NET MVC随记汇总
  7. php 历史版本下载地址
  8. [wiki]陶德曼调停
  9. Qt__状态栏(statusBar)
  10. ArrayMap代码分析