SDUT3257 & 3258 (素数)

题目链接:SDUT3258

题目大意:

一个整数,可以被表示为另一个整数的平方,这个整数称为平方数。

给你一个序列ai ~aj,规模为1e5,让你找出有多少对(ai,aj),使得ai×aj为平方数。

思路

唯一分解定理:任何一个大于1的数,都可以拆分成若干素数的乘积。

有了这个定理再看题目要求可知,平方数就一定能表示为若干素数的偶次幂的乘积。

所以枚举所有的素因子,如果出现偶次幂,忽略,如果是奇次幂就记录在对于的位置factor[ n ]++。

最后统计有多少个可以配对的因数就行了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn  = 1000000 + 10;
bool isprime[maxn];
int prime[maxn];
int num[maxn/10];
int factor[maxn];
	int k = 0 ;
void init(){
	isprime[0]=1, isprime[1] =1;
	for(int i=2;i<=sqrt((double)maxn);i++){ 
		if(!isprime[i]){
			prime[k++] = i;
			for(int j = i*2;j<=maxn;j+=i)
				isprime[j] = 1;
		}
	}
}
int main(){
	int t;
	init();
	scanf("%d",&t);
	while(t--){
		long long  ans = 0;
		int n;
		memset(factor,0,sizeof(factor));
		scanf("%d",&n);
		for(int i=0;i<n;i++)
			scanf("%d",&num[i]);
		for(int i=0;i<n;i++){
			int t = num[i];
			int remain = 1;
			for(int j = 0;j<k;j++){
				int times = 0;
				while(t % prime[j] == 0){
					t/=prime[j];
					times ++;
				}
				if(times & 1){ //如果是奇数个素因子
					remain*=prime[j];
				}
				if( !isprime[t] || t == 1){ //如果
					remain*=t;
					break;
				}
			}
			ans += factor[remain];
			factor[remain]++;
		}
		printf("%lld\n",ans);
	}
	return 0;
}


题目链接:SDTU3257


和上一个题一样,不过这题求得是立方数。


一样的思路,如果素因子出现的次数是3的倍数,忽略, 如果mod3 == 1,那么就去找mod3 == 2的配对, 如果 mod3 == 2,就去找mod3 == 1的配对。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn  = 1000000 + 10;
bool isprime[maxn];
int prime[maxn];
int num[maxn/10];
int factor[maxn];
int k = 0 ;
void init(){
	isprime[0]=1, isprime[1] =1;
	for(int i=2;i<=1000;i++){ //只需要找1000下的素数即可
		if(!isprime[i]){
			prime[k++] = i;
			for(int j = i*2;j<=1000;j+=i)
				isprime[j] = 1;
		}
	}
}
int main(){
	int t;
	init();
	scanf("%d",&t);
	while(t--){
		long long  ans = 0;
		int n;
		memset(factor,0,sizeof(factor));
		scanf("%d",&n);
		for(int i=0;i<n;i++)
			scanf("%d",&num[i]);
		for(int i=0;i<n;i++){
			int t = num[i];
			long long  self = 1; //代表自己多余的因数
			long long  partner = 1; //代表需要配对的因数
			int isadd = 0;
			for(int j = 0;j<k;j++){
				int times = 0;
				while(t % prime[j] == 0){
					t/=prime[j];
					times ++;
				}
				if(times % 3 == 1){
					self*=prime[j];
					partner = partner*prime[j]*prime[j];
				}
				else if(times % 3 == 2){
					self = self*prime[j]*prime[j];
					partner*=prime[j];
				}
				if(partner >1000000 ||self >1000000 ){ //如果超1000000则不可能有配对
					isadd = 0;break;
				}
				if(t == 1){
					isadd = 1;break;
				}
			}
			if(isadd && t == 1){
				ans += factor[partner]; 
				factor[self]++;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}




转载于:https://www.cnblogs.com/chaiwenjun000/p/5321137.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值