SDUT 3258 Square Number【思维+高效预处理】
来源:互联网 发布:淘宝怎么贷款最高额度 编辑:程序博客网 时间:2024/05/23 23:18
Square Number
Problem Description
In mathematics, a square number is an integer that is the square of an integer. In other words, it is the product of some integer with itself. For example, 9 is a square number, since it can be written as 3 * 3.
Given an array of distinct integers (a1, a2, ..., an), you need to find the number of pairs (ai, aj) that satisfy (ai * aj) is a square number.
Input
The first line of the input contains an integer T (1 ≤ T ≤ 20) which means the number of test cases.
Then T lines follow, each line starts with a number N (1 ≤ N ≤ 100000), then N integers followed (all the integers are between 1 and 1000000).
Output
For each test case, you should output the answer of each case.
Example Input
1 5 1 2 3 4 12
Example Output
2
Hint
Author
题目大意:
给你N个数,让你从这N个数中找一共有多少对(i,j),使得Ai*Aj是一个平方数。
有一道题和这个题还是有相像之处的高效枚举做法题:http://blog.csdn.net/mengxiang000000/article/details/70477092
思路:
不难发现,如果Ai*Aj是平方数,Aj*Ak是平方数,那么Ai*Ak也一定是一个平方数。
那么其实这些数是可以分成堆的,对于一堆数来讲,任意取其中两个数都可以相乘变成一个平方数。
那么考虑预处理,我们直接预处理是O(1e6*1e6)肯定要超时的,即使我们链表处理将处理完的数去掉也是要超时的,优化不掉多少时间复杂度。
这个时候我们这样考虑:
对于和2分成一堆的元素:
2 8 18 32 50.........................假设我们现在已知2*50==100是一个平方数,我们要找一个数X.使得2*X是一个平方数且X>50的话,我们肯定考虑的过程是这样的:
50+2是不是平方数?50+2*2是不是平方数?50+2*3是不是平方数?50+2*4是不是平方数?
那么很显然,我们没有必要在第二层for的时候每次+1.我们可以每次+i...
那么对应我们预处理需要的操作数约为:1e6+1e6/2+1e6/3+1e6/4.............................很显然我们过程中还可以标记被分完堆的数字,对于这些已经分完堆了的数我们就没有必要继续枚举和其构成一堆的数字了,
所以总体操作数我们约可以记为1e7左右(估计出的)。
那么我们对于T组数据,我们O(n)+map维护一下答案即可。
Ac代码:
#include<stdio.h>#include<math.h>#include<string.h>using namespace std;#define ll long long intll f[1000800];ll vis[1000700];ll a[1000700];ll cont[1000700];void init(){ memset(f,0,sizeof(f)); memset(vis,0,sizeof(vis)); ll cnt=0; for(ll i=1;i<=1000000;i++) { if(f[i])continue; f[i]=++cnt; for(ll j=i*2;j<=1000000;j+=i) { ll tmp=i*j; ll tmpp=(ll)sqrt(tmp); if(tmpp*tmpp==tmp) { f[j]=cnt; } } }}int main(){ init(); int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); memset(cont,0,sizeof(cont)); ll sum=0; for(int i=0;i<n;i++) { int x; scanf("%d",&x); sum+=cont[f[x]]; cont[f[x]]++; } printf("%lld\n",sum); }}
- SDUT 3258 Square Number【思维+高效预处理】
- 【SDUT 3258】Square Number
- sdut 3258 Square Number
- SDUT 3258 Square Number
- sdut 3258 Square Number 打表
- SDut 3257 Cube Number && SDUT 3258 Square Number 超详细题解(数学)
- SDUT 3258 山东省第六届ACM程序设计大赛——H Square Number
- sdut 3258 Square Number(山东声第六届ACM程序设计竞赛)
- SDUT 3258 Square Number(2015年山东省第六届ACM大学生程序设计竞赛)
- Square Number-3258拆平方
- “浪潮杯”山东省第6届acm省赛 sdut3258 Square Number sdut 3257 Cube Number
- Square Number
- Square Number
- SDUT 1919 规律,思维
- SDUT 3902 company【思维】
- SPOJ - Palin Square【预处理+枚举】
- float number square root
- Lesson2 Square number
- windows下react-native环境配置
- reactNative中的通知
- 2017年个人目标及计划
- 【APIO2010T1】特别行动队-DP斜率优化
- 阿里用技术帮用户剁手——《尽在双11——阿里巴巴技术演进与超越》
- SDUT 3258 Square Number【思维+高效预处理】
- 短信验证-互亿短信
- oracle存储过程基本使用
- 【SQL之查询】MySQL查询今天、昨天、上周、近30天、去年等的数据的方法
- 二叉树14:把二叉树打印成多行
- HDU5334(构造,思维)
- spring整合redis(集群、主从)
- Linux下安装MySQLdb模块(Python)
- C#实现环信用户和群组操作