E1. Square-free division (easy version)

该博客讨论了一种算法问题,要求将序列分成连续段,使得每段内任意两个数相乘不是平方数。解决问题的关键在于分析数的质因数分解,通过筛素数的方法检查每个数的奇数次质因数,更新段数。博客提供了一个C++代码实现,并展示了如何优化内存使用以避免超时。
摘要由CSDN通过智能技术生成

E1. Square-free division (easy version)

题目
在这里插入图片描述

标题

题目大意
给你一个序列要求,要求你分成连续的段,每段里面任意两个数相乘不为平方数,问最少能分成几段。
思路
任意两个数之积为平方数,可以从这个数拆分成最小质数幂次方之积来考虑,例如a= r 1 x ∗ r 2 y ∗ r 3 z . . . . . . . . . . r n w r_1^x*r_2^y*r_3^z..........r_n^w r1xr2yr3z..........rnw 是质数拆分后的形式,两个数相乘想为平方数,那么只需要考虑质因数为奇数次方就可以,偶数次方本来就可以做完全平方数,只有当是奇数次方时,只有当两个数的奇数次方质因数相等,那么二者之积才为平方数,测试这个数的质因数的幂次方为奇数,可以用筛素数类似做法,每次输入一个元素,将其筛查,然后通过map访问,当这个数的奇次质因数在当映射存在时,那么清空之前的映射,然后段数加一,如果不存在就压入映射中,继续访问。注意在筛的过程中如果开long long会超时。

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define sl(n) scanf("%lld",&n)
#define pl(n) printf("%lld",n)
#define sdf(n) scanf("%lf",&n)
#define pdf(n) printf("%.lf",n)
#define pE printf("\n")
#define ull unsigned long long
#define pb push_back
#define pre(n) for(ll i=1;i<=n;i++)
#define rep(n) for(ll i=n;i>=1;i--)
#define pi pair<ll,ll>
#define fi first
#define se second
int getprime(int x){
	int sum=1,cnt=0,i;
	if(x==1)return 1;
	for(i=2;i*i<=x;i++){
		cnt=0;
		if(x%i==0){
			while(x%i==0){
				cnt++;
				x/=i;
			}
		}
		if(cnt%2)sum*=i;
	}
	return sum*x;
}
int main(){
	int sum=0,t,n,k,temp,kk;
	IOS;
	scanf("%d",&t);
	while(t--){
		map<int,int>a;
		scanf("%d %d",&n,&k);
		sum=1;
		while(n--)
		{
			scanf("%d",&temp);
			kk=getprime(temp);
			if(a[kk])
			{
				sum++;
				a.clear();
			}
			a[kk]++;
		}
		printf("%d\n",sum);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值