Codeforces Round #708 (Div. 2)E1
E1. Square-free division (easy version)
本题的题意是分串,要求串中任意两个数相乘不能是完全平方数。
首先注意到一个数可以分解为a=p1^a1*p2^a2*p3^a3*p4^a4;
那么如果a*b为完全平方数,即他们的每个质因子的幂全都为偶数。
那么对于单个数我们对于其所有的质因子只留下奇数次幂的且将其幂变为1.
如果存在一个数经过该操作后和另一个数经过该操作后相同,则他们相乘后的数为完全平方数。(因为他们相乘后所有的质因子的幂都变成了偶数)
但直接在线拆解质因子又会TLE。因此我们需要离线的预处理每个数的奇数次幂的质因子。
这时我们需要用到线性筛。我们知道线性筛中每个数都只会出现一次。且出现的方式是他最小的质因子乘以一个数。那么我们根据这个数的奇数次幂质因子再乘上自己最小的质因子即可得到原数的奇数次幂质因子(需要注意的是如果这个数的奇数次幂质因子中刚好有该最小质因子,则应该除去他,因为如果相乘的话该奇数次幂质因子会变成偶次幂)。因此我们可以离线线性的处理1~1e7中每个数的奇数次幂质因子。并通过o1查询。
之后拆分的时候我们可以用set来判断该数是否已经出现在前面了。若未出现,则塞进set,若已经出现了,则set清空,同时进入下一个子串,即ans++
AC代码如下:
#include<cstdio> #include<cctype> #include<iostream> #include<vector> #include<algorithm> #include<queue> #include<cstring> #include<set> #define MAXN 10000005 using namespace std; typedef long long ll; #define int long long int f[MAXN]; vector<int>v; bool not_prime[MAXN]; void prime(){//线性筛 f[1]=1; not_prime[0]=not_prime[1]=1;; for(int i=2;i<MAXN;i++){ if(!not_prime[i]){//如果i是质数 v.push_back(i);//v中存储质数 f[i]=i;//由该质数构造的数就是他本身 } int l=v.size(); for(int j=0;j<l;j++){ int k=i*v[j];//判断k的最小奇数次质因数乘积 if(k>=MAXN) break; if(f[i]%v[j]){//由于k=i*v[i],f[i]为i的最小奇数次质因数乘积, f[k]=f[i]*v[j];//若不能整除,说明v[j]*i后,k会多一个质因数因子,即f[k]比f[j]多了个v[j]因子 }else{ f[k]=f[i]/v[j];//故若能整除,则说明v[j]是f[i]的一个奇数次质因数,那么v[j]为k的偶数次 } not_prime[k]=1;//1表示不是质数,0表示是质数 if(i%v[j]==0) break; } } } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); prime(); int t; cin>>t; while(t--){ int n,k,ans=1; cin>>n>>k; set<int>s; for(int i=0,a;i<n;i++){ cin>>a; if(s.count(f[a])){ ans++; s.clear(); } s.insert(f[a]); } cout<<ans<<endl; } return 0; }

浙公网安备 33010602011771号