zoukankan      html  css  js  c++  java
  • 【Codeforces Round #694 (Div. 1) B】Strange Definition

    题目链接

    链接

    翻译

    每秒钟会对原数组进行如下操作,对于每一个数组中的元素。找到整个数组中和它【相关】的数字,将这些数字全都乘起来

    然后用来代替这个元素。

    【相关】表示两个数字的最小公倍数和最大公因数的商是一个完全平方数。

    然后让你回答 (q) 个询问,表示 (w) 秒钟之后,数组中每个元素【相关】的数字的个数的最大值。

    题解

    得知道 (lcm(x,y)=frac{x*y}{gcd(x,y)}) 这样的话,就知道两个数字相关当且仅当他们相乘是一个完全平方数(分母已经是 (gcd) 的平方了)。

    那么什么样的两个数字 (x)(y) 会满足相乘是一个完全平方数呢?

    从质因数分解的角度考虑。

    考虑两个数字分解之后所有的 公共 质因子 (p),如果两者分解出来的指数 (q1)(q2) 的和都是偶数。

    那么这是它们的乘积是完全平方数的一个先决条件。

    还有非公共的部分,这部分咋办? 会发现因为不是公共的质因子,所以如果有一方对应的非公共质因子的指数为奇数。

    那么它们相乘就不是完全平方数了,比如 (2=2)(6=2*3) 其中 (6) 的质因子 (3) 不是公共质因子,且指数为奇数 (1)

    所以它们相乘就不是完全平方数了,因此非公共质因子的指数都要为偶数。

    而公共质因子的指数相加为偶数,先决条件就是它们俩的指数的奇偶性相同。

    也即对应的质因子指数 (q_i\%2) 的值要相同。

    则我们可以这样,对于数组中所有数字的质因数分解,把它都写成 (x=p_1^{q_1\%2}*p_2^{q_2\%2}...*p_k^{q_k\%2}) 的形式。

    这样我们就可以根据这个新的 (p_1^{q_1\%2}*p_2^{q_2\%2}...*p_k^{q_k\%2}) 标识(运算的结果),相同标识的分到一个集合中去,将原数组中的数字分成很多个不同的集合了。

    会发现 同一个集合里面的数字都是互相相关的,相乘之后指数都是偶数。且非公共质因子的指数也用这个模 (2) 操作区分开来了,如果为偶数

    就直接变成数字 (1) 了,不会成为集合的标识。

    那么我们就得到很多个集合了,有什么用呢?

    一开始 (0) 时刻,我们只要统计所有的集合的大小的最大值即可。

    大于 (0) 时刻,现在要开始变化了。

    会发现,如果集合的大小为偶数,那么里面所有的数字相乘的话,最后的结果就是所有新的数字的指数都变成偶数,那么在指数模 (2) 的情况下,就全都变成数字 (1) 了。

    则对应集合会和以 (1) 为标识的集合合并到一起。

    而集合的大小为奇数的话,那么每个数字的质因子的指数在经过奇数次相加之后,还是一个奇数, 则集合大小不变,里面的数字也不变(指数还是都是 (1))。

    所以,统计一下 (1) 集合,以及集合大小为偶数的集合,记作 (cnt1),然后一开始所有集合中大小最大的那个集合的大小,记作 (cnt2),这里的 (cnt2) 能够覆盖

    奇数大小集合不变的情况。

    所以在 (w>=1) 的时候,输出 (max(cnt1,cnt2)) 而在 (w=0) 的时候,直接输出 (cnt2) 就好,代码中用的不是 (cnt) 等名称, 不要 (confuse) 了...

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    int n;
    map<int,int> dic;
    
    int main() {
    	#ifdef LOCAL_DEFINE
    		freopen("in.txt", "r", stdin);
    	#endif
    	ios::sync_with_stdio(0), cin.tie(0);
    	int T;
    	cin >> T;
    	while (T--) {
            dic.clear();
            cin >> n;
            for (int i = 1;i <= n; i++){
                int x;
                cin >> x;
                for (int j = 2;j*j <= x; j++){
                    while (x%(j*j)==0){
                        x/=j*j;
                    }
                }
                dic[x]++;
            }
            int a = 0, b = 0;
            for (auto tmp: dic){
                if (tmp.first==1 || tmp.second%2==0){
                    b+=tmp.second;
                }
                if (tmp.second > a){
                    a = tmp.second;
                }
            }
            int q;
            cin >> q;
            for (int i = 1;i <= q; i++){
                LL w;
                cin >> w;
                if (w == 0){
                    cout << a << endl;
                }else{
                    cout << max(a,b) << endl;
                }
            }
    
    	}
    	return 0;
    }
    
  • 相关阅读:
    大数据分析服务器硬件配置如何选择
    Laravel 在哪些地方使用了 trait ?
    PHP 中 Traits 的简单使用
    Laravel中Trait的用法实例详解
    Trait 概览
    Laravel trait 使用心得
    Laravel 5 项目部署到生产环境的实践
    Laravel 的 Events(事件) 及 Observers(观察者)
    Eloquent Observer 的小坑
    Ubuntu 网卡多个 IP 地址
  • 原文地址:https://www.cnblogs.com/AWCXV/p/14287436.html
Copyright © 2011-2022 走看看