ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1497E1 Square-free division (easy version)题解

2021-10-21 13:03:04  阅读:193  来源: 互联网

标签:division 平方 Square 幂次 奇数 int 题解 一个 因子


题意

给你一个长度为\(n\)的序列,你需要把这个序列分成若干段,使得每一段满足:从这一段中任意选择两个数,使得这两个数的乘积不为完全平方数。最小化分的段数,问你最少分成多少段。

分析

发现完全平方数其实就是质因数分解之后每一个质因子的幂次都为偶数的数,那么只要有一个质因子的幂次为奇数,这个数就不是完全平方数。所以对于一个数的一些幂次为奇数的因子,必须要有一个数,这个数的所有幂次为奇数的因子与他完全一致,这两个数才能凑成完全平方数。所以我们就有一个暴力的做法:我们从左往右处理每一个数字,每遇到一个数字我们就把这个数字质因数分解。然后我们把它的幂次为偶数的质因子忽略,只考虑它幂次为奇数的质因子,如果它之前存在一个数,那个数的奇数次质因子集合与它完全相同,那么这两个数显然不能放在同一段里,也就是需要贪心的分成两段,如果没有,那么就把这个数加入之前的那一段然后把这个数的质因子记录下来。
考虑怎么实现,发现需要一个可以支持插入和查询一个集合是否存在,可以用哈希,但是我们发现,考虑所有的质数,如果他们不同,那么他们的乘积也肯定不同,所以我们只需要用乘积来代表一个质因数的集合然后用map维护即可。
总复杂度为\(O(n\sqrt{INT\_MAX)}\),但是能过(

代码


/* Creat on Xishui's iPad 
    Author: Xishui
    date: 21/10/21
    Language: C++
*/

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,k;
int devide(int x){
    int ret=1;
    if(x==1)
        return 1;
    for(int i=2;i*i<=x;i++){
        int cnt=0;
        while(x%i==0){
            x/=i;
            cnt++;
        }
        if(cnt%2)
            ret*=i;
    }
    return ret*x;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&k);
        int ans=0;
        map<int,int>ret;
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);    
            int res=devide(x);
            if(ret[res]){
                ans++;
                ret.clear();
            }
            ret[res]=1;
        }
        printf("%d\n",ans+1);
    }
    return 0;
}

标签:division,平方,Square,幂次,奇数,int,题解,一个,因子
来源: https://www.cnblogs.com/xishuixs/p/15432859.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有