• 【CodeForces】#694 D. Strange Definition


    CodeForces #694 D. Strange Definition

    题目链接

    题意

    定义数字 (x)(y) 是“相邻”的当且仅当 (frac{lcm(x,y)}{gcd(x,y)}) 是一个平方数。

    给定一个长度为 (n) 的数组 (a)

    每过一秒,数组 (a) 会发生变化:(a_i) 会变成数组 (a) 中与其“相邻”的所有数字的乘积。

    定义 (d_i) 为数组 (a) 中与 (a_i) “相邻” 的数字个数。

    定义数组 (a) 的美丽值为 (max_{1leq i leq n }d_i)

    给出 (q) 个询问,每次询问给出当前时间 (w),问当前数组 (a) 的美丽值。

    思路

    (w) 的范围这么大,考虑 (a) 数组可能变化有限次后,答案不再发生变化。

    先考虑如何求美丽值。

    题目中对于“相邻”的定义可以简化:

    [frac{lcm(x,y)}{gcd(x,y)} =frac{frac{x imes y}{gcd(x,y)}}{gcd(x,y)}=frac{x imes y}{gcd(x,y) imes gcd(x,y)} ]

    显然只要 (x imes y) 是平方数,它俩就“相邻”。

    如果(x imes y)是平方数,就要求 (x)(y) 对应质因子的幂次奇偶性相同。

    此时分别将 (x,y) 中偶数次幂的质因子删除掉,保留奇数次幂的质因子。

    如果 (x = y)(x imes y) 是平方数,否则不是。

    经过上述处理的数组 (a) 中,出现次数最多的数字的出现次数就是数组 (a) 的美丽值

    再看 (a) 发生变化对于其美丽值的影响。

    前面说过只有 (x=y) 的时候,(x imes y)才是平方数

    那么 (a) 数组发生变化时,(a_i) 变成了 ({a_i}^{d_i})

    同样变化之后,对于 (a_i) 只保留奇数次幂的质因子。

    如果 (d_i) 是偶数,(a_i) 就变成了 (1),否则还是 (a_i)

    如果又过了一秒,那么此时能变成 (1)(a_i) 已经变成 (1) 了,不能变的还是不能变。

    可知:变化 (1) 次和变化多次的答案是一样的

    因为只会有不是 (1) 的变成 (1)

    只需判断变化后 (1) 的数量是否大于没变化之前的答案,二者输出较大值。

    变化后 (1) 的数量为:

    没变化之前出现次数为偶数的非 (1) 的数字+原本 (1) 的出现次数。

    代码

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const ll mod = 1e9 + 7;
    const double eps = 1e-6;
    const ll inf = 0x3f3f3f3f;
    const ll N = 1e6 + 10;
    
    int arr[N], sign[N];
    int vis[N], pri[N], tot;
    void solve(int n)
    {
        for (int i = 2; i <= n; i++) {
            if (!vis[i]) {
                sign[i] = 1;
                pri[++tot] = i;
            }
            for (int j = 1; j <= tot; j++) {
                if (i * pri[j] > n)
                    break;
                vis[i * pri[j]] = pri[j]; //纪录最小的素因子
                if (i % pri[j] == 0)
                    break;
            }
        }
    }
    int sum[N];
    vector<int> vec;
    int main()
    {
        solve(1000000);//欧拉筛
        int T;
        scanf("%d", &T);
        while (T--) {
            vec.clear();
            int n;
            scanf("%d", &n);
            int ans0 = 0, ans1 = 0;//ans0 表示出现此处最多的数字的出现次数
            for (int i = 1; i <= n; i++) {
                scanf("%d", &arr[i]);
                int tmp = 1, j = 1;
                while (arr[i] >= pri[j]) {//只保留奇数次幂质因子
                    int num = 0;
                    while (arr[i] % pri[j] == 0) {
                        num++;
                        arr[i] /= pri[j];
                    }
                    if (num % 2)
                        tmp *= pri[j];
                    j++;
                    if (sign[arr[i]]) {
                        tmp *= arr[i];
                        break;
                    }
                }
                vec.pb(tmp);
                ans0 = max(ans0, ++sum[tmp]); 
            }
            int even = 0;
            for (int v : vec) {
                if (v != 1) {
                    if (sum[v] % 2 == 0)//未变化时出现次数为偶数且非 1 的数字数量
                        even++;
                } else {
                    ans1++;//未变化时 1 的数量
                }
            }
            for (int v : vec) {
                sum[v] = 0;
            }
            int q;
            scanf("%d", &q);
            while (q--) {
                ll w;
                scanf("%lld", &w);
                if (w == 0) {
                    printf("%d
    ", ans0);
                } else {
                    printf("%d
    ", max(ans0, ans1 + even));
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    jsp页面中使用 splitfn:split注意事项
    【SQL】- 基础知识梳理(二)
    【SQL】- 基础知识梳理(一)
    面向对象编程思想-解释器模式
    NPOI操作Excel
    面向对象编程思想-备忘录模式
    面向对象编程思想-访问者模式
    面向对象编程思想-责任链模式
    面向对象编程思想-策略模式
    面向对象编程思想-状态模式
  • 原文地址:https://www.cnblogs.com/valk3/p/14266303.html
Copyright © 2020-2023  润新知