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
r1x∗r2y∗r3z..........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;
}