【map】【分解质因数】CDOJ1572 Espec1al Triple

先把公比为1,即前项 中项 末项相同的统计出来。对每一类数C(n,3)即可。

然后我们发现,因为a1*a3=(a2)^2,所以a1和a3进行质因子分解之后,每一个质因子的指数的奇偶性必然相同,否则无法满足乘积为完全平方数。

然后sqrt(100000)以内的素数只有65个,我们对于每一个数,用unsigned long long存一个01串,代表前64个素因子的奇偶性,再单独用一个布尔存第65个。

然后该数还有可能有一个大素因子(>sqrt(x)),单独存一下,这样用一个三元组唯一标示每一个数。

a1和a3的三元组必然完全相同。

于是对于这样一个三元组,开个map套vector记录下符合其的数的个数(不超过log个),然后就很容易统计了。

复杂度其实很低,就是常数挺大。

#include<cstdio>
#include<bitset>
#include<map>
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
struct Point{
	ull S;
	int x;
	int y;
	Point (const ull &A,const int &X,const int &Y){
		S=A;
		x=X;
		y=Y;
	}
	Point(){

	}
};
bool operator < (const Point &a,const Point &b){
	if(a.S!=b.S){
		return a.S<b.S;
	}
	if(a.x!=b.x){
		return a.x<b.x;
	}
	return a.y<b.y;
}
map<Point,vector<int> >ma;
ll ans;
bool vis[100000];
int pri[1000],pr;
void shai(){
	vis[1]=1;
	for(int i=1;i*i<=100000;++i){
		if(!vis[i]){
			pri[pr++]=i;
			for(int j=i*i;j*j<=100000;j+=i){
				vis[j]=1;
			}
		}
	}
}
int n,m,a[1000010];
ll num[100010];
int main(){
//	freopen("e.in","r",stdin);
	shai();
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		++num[a[i]];
	}
	for(int i=1;i<=100000;++i){
		ans+=(num[i]*(num[i]-1ll)*(num[i]-2ll))/6ll;
	}
	sort(a+1,a+n+1);
	int last=1;
	for(int i=1;i<=n;++i){
		if(a[i]!=a[i-1]){
			int x=a[i];
			ull S=0;
			for(int j=0;j<pr-1;++j){
				int cnt=0;
				while(x%pri[j]==0){
					++cnt;
					x/=pri[j];
				}
				if(cnt%2!=0){
					S|=((ull)1<<j);
				}
			}
			int y=0,z;
			while(x%pri[pr-1]==0){
				++y;
				x/=pri[pr-1];
			}
			y%=2;
			z=x;
			vector<int> v=ma[Point(S,y,z)];
			for(int j=0;j<v.size();++j){
				ans+=num[a[i]]*num[v[j]]*num[(int)(sqrt((ll)a[i]*(ll)v[j])+0.5)];
			}
			ma[Point(S,y,z)].push_back(a[i]);
			last=i;
		}
	}
	cout<<ans<<endl;
	return 0;
}
时间: 2024-08-05 23:52:40

【map】【分解质因数】CDOJ1572 Espec1al Triple的相关文章

uva10780(分解质因数)

可以直接用高精度来暴力求. 也可以不用高精度: 把m分解质因数,记录每个因数和它的次数.然后计算每个因数在n的阶乘里出现了多少次,再把这个次数除以它在m中的次数,就是可能的k值.取最小的k. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #

【CodeM初赛】T4 分解质因数+暴力

题目描述树链是指树里的一条路径.美团外卖的形象代言人袋鼠先生最近在研究一个特殊的最长树链问题.现在树中的每个点都有一个正整数值,他想在树中找出最长的树链,使得这条树链上所有对应点的值的最大公约数大于1.请求出这条树链的长度. 输入描述:第1行:整数n(1 ≤ n ≤ 100000),表示点的个数.第2~n行:每行两个整数x,y表示xy之间有边,数据保证给出的是一棵树.第n+1行:n个整数,依次表示点1~n对应的权值(1 ≤ 权值 ≤ 1,000,000,000). 输出描述:满足最长路径的长度

[Codeforces 1246B] Power Products (STL+分解质因数)

[Codeforces 1246B] Power Products (STL+分解质因数) 题面 给出一个长度为\(n\)的序列\(a_i\)和常数k,求有多少个数对\((i,j)\)满足\(a_i \times a_j = x^k (x \in \mathbb{N}^+)\).即这两个数乘起来恰好为一个正整数的\(k\)次方 \(a_i,n \leq 10^5\) 分析 考虑\(x^k\)的质因数分解式 , 那么每一项的指数一定是k的倍数,即 \(k|x_i\). 因此对于每个 \(a_i\)

分解质因数模板

/*==================================================*| 分解质因数,可能有些地方需要改为long long \*==================================================*/ const int MAXN=100010; int prm[MAXN+1]; bool is[MAXN+1]; int getprm(int n){ int i, j, k = 0; int s, e = (int)(sqrt

java编程题 --分解质因数

package Solve; import java.util.Scanner; public class Solve { static Scanner scan = new Scanner(System.in); public static void main(String[] args) { System.out.println("请输入一个正整数:"); int num = scan.nextInt(); System.out.print(num + " = "

POJ 2773 Happy 2006 (分解质因数+容斥+二分 或 欧几里德算法应用)

Happy 2006 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 10309   Accepted: 3566 Description Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9...are a

codevs 1792 分解质因数

1792 分解质因数 题目描述 Description 编写一个把整数N分解为质因数乘积的程序. 输入描述 Input Description 输入一个整数 N 输出描述 Output Description 输出 分解质因数 .拆成几个质数相乘的形式,质数必须从小到大相乘 样例输入 Sample Input 756 样例输出 Sample Output 756=2*2*3*3*3*7 #include<cstdio> #include<cmath> #include<str

代码实现:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5

import java.util.Scanner; /*题目:将一个正整数分解质因数.例如:输入90,打印出90=2*3*3*5. 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: (1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可. (2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数n,重复执行第一步. (3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步.*/ public class Test

分解质因数

package java算法; /** * 任意整数分解 题目:将一个正整数分解质因数.例如:输入90,打印出90=2*3*3*5. * 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: (1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可. * (2)如果n>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步. * (3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步. * * @author to