其他分享
首页 > 其他分享> > Namomo Camp Div1 合适数对(数据加强版)

Namomo Camp Div1 合适数对(数据加强版)

作者:互联网

合适数对(数据加强版)
思路:
我们考虑一个数什么时候可以表示为\(x ^ {k}\),先把\(x\)进行质因数分解可以得到\(x = p_{1}^{t_1} * p_{2} ^ {t_2} \dots * p_{n} ^ {t_n}\),所以\(x ^ {k}\)就可以表示为\(x ^ {k} = p_{1} ^ {k_1} * p_{2} ^ {k_2} \dots * p_{n} ^ {k_n}\), 其中\(k_1, k_2, k_3 \dots k_t\) 都是\(k\)的倍数
所以我们在考虑\(p*q=x^{k}\)的时候,只需要保证\(p * q\)分解质因数的结果中每一个因数的指数都可以被\(k\)整除。那么我们对序列中每一个数进行质因数分解的时候,对于每一个质因数的幂次都\(\%k\)并将结果存在\(p\)中,即\(p = p_{1} ^ {k_1} * p_{2} ^ {k_2} \dots * p_{n} ^ {k_n}\), 在我们得到\(p\)之后,我们只需要判断我们可以求得有多少个匹配的\(q\)并更新答案。
由于数据量达到了\(10 ^ {7}\),如果用\(O(\sqrt{n})\)的朴素判素数明显是不行的,所以我们应该用欧拉筛\(O(n)\)来求的所有数的最小质因子。当然我们在筛素数的时候很明显所有的偶数都是一定会被\(2\)给筛掉的,所以我们在筛素数的时候可以直接将所有的偶数跳过,不对它们筛素数,这样可以优化一下筛法的常数。

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;
        }
    }
}

\(code\)

int n, k;
    n = read(), k = read();

    std::vector<int> a(n);
    for (auto &I : a) I = read();
    int mx = *max_element(a.begin(), a.end());
    
    Eular(mx);
    std::vector<i64> mp(mx + 1);
    i64 ans = 0;
    for (int i = 0; i < n; i ++ ) {
        i64 p = 1, q = 1;
        while (a[i] > 1) {
            int val = (a[i] & 1) ? minp[a[i]] : 2;
            int cnt = 0;
            while (a[i] % val == 0) {
                cnt ++ ;
                a[i] /= val;
            }
            while (cnt >= k) cnt -= k;

            p *= qmi(val, cnt);
            if (cnt) q *= qmi(val, k - cnt);
            if (q < 0 || q > mx) q = 0;
        }
        ans += mp[q];
        mp[p] ++;
    }
    printf("%lld\n", ans);

标签:dots,cnt,数对,加强版,val,int,Camp,++,mx
来源: https://www.cnblogs.com/Haven-/p/16142874.html