其他分享
首页 > 其他分享> > Codeforces Round #694 (Div. 2)

Codeforces Round #694 (Div. 2)

作者:互联网

D

  该题目告诉我们两个数\(x,y\)它们的\(\frac{lcm(x, y)}{gcd(x, y)}\)如果是一个完全平方数的话,我们就称它们是相邻的。 现在给我们一个长度为\(n\)的数组\(a\),每一秒数组中的每个元素\(a_i\)都被数组中与当前值相邻的所有元素(包括其自身)的乘积所取代。让\(d_i\)是每一个\(a_i\)的相邻的值,一个数组的美丽度被定义为\(max_{1\leq i \leq n} d_i\)。现在有\(q\)次询问,每次都会让我们求出来\(w\)秒后这个数组的美丽度是多少。


思路:
  看到\(\frac{lcm(x,y)}{gcd(x, y)}\)是一个完全平方数,可以想着去推一下式子,因为\(lcm(x, y) = \frac{x * y}{gcd(x, y}\),所以可以将原式推导为\(\frac{x * y}{(gcd(x, y)) ^ {2}}\) 是一个完全平方数,所以可以写成\((\frac{\sqrt{x * y}}{gcd(x, y)}) ^ 2 == x ^ 2\)当且仅当\(x * y\)是完全平方数的时候该等式方才成立。那么问题就转化成了将\(x * y\)分解质因数,其中每一个因子的幂次都可以被\(2\)整除也就是\(x * y = p_{1} ^ {k_1} * p_{2} ^ {k_2} \dots * p_{n} ^ {k_n}\),其中\(k_1,k_2,k_3 \dots k_n\)都是\(2\)的倍数。因此我们只需要记录\(z_i = p_{1} ^ {k_1\%2} * p_{2} ^ {k_2 \% 2} \dots * p_{n} ^ {k_n \% 2}\) ,如果\(z_i == z_j\)说明两数相乘的质因子的幂次都为偶数,是个完全平方数。
  用欧拉筛来得到每一个数的最小质因子

void Eular(int n) {
    prime[idx ++ ] = 2;
    minp[2] = 2;
    st[2] = true;
    for (int i = 3; i <= n; i += 2) {
        if (!st[i]) prime[idx ++ ] = i, minp[i] = i, st[i] = true;
        for (int j = 0; prime[j] * i <= n; j ++ ) {
            st[prime[j] * i] = true;
            minp[prime[j] * i] = prime[j];
            if (i % prime[j] == 0) break;
        }
    }
}

在我们得到\(z_i\)的时候如果出现了偶数次幂,那么我们后面在判断完全平方数的时候还是会被分解掉,所以我们只需要在出现奇数次幂的时候在\(z_i\)的基础上乘上一个\(p_{i} ^ {1}\)

void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    rep(i, 1, n + 1) std::cin >> a[i];
    std::map<int, int> mp;
    rep(i, 1, n + 1) {
        int val = a[i];
        int z = 1;
        while (val > 1) {
            int p = minp[val];
            int cnt = 0;
            while (val % p == 0) {
                cnt ++;
                val /= p;
            }
            if (cnt % 2 == 1) z *= p;
        }
        mp[z] ++;
    } // 找到匹配上的另一个数

    int cnt0 = 0;
    for (auto &p : mp) cnt0 = std::max(cnt0, p.second);
    for (auto &p : mp) {
        if (p.first == 1 || p.second % 2 == 1) continue;
        mp[1] += p.second;
        mp[p.first] = 0;
    }

    int cnt1 = 0;
    for (auto &p : mp) cnt1 = std::max(cnt1, p.second);
    int m;
    std::cin >> m;
    while (m -- ) {
        int op;std::cin >> op;
        std::cout << (op == 0 ? cnt0 : cnt1) << "\n";
    }
}

标签:std,frac,val,694,int,Codeforces,mp,Div,gcd
来源: https://www.cnblogs.com/Haven-/p/16142900.html