cf1033 D. Divisors(数学)

题意:

\(\prod a_i\) 的不同因子数量。答案对998244353取模。

\(n\le 500, 1\le a_i\le2e18,\) 每个 \(a_i\) 只有 \(3\sim 5\) 个不同因子。

思路:

范围太大了,分解质因数会tle。

因为每个 \(a_i\) 只有 \(3\sim 5\) 个不同因子,所以 \(a_i\) 只能是四种形式之一:\(p^2,p^3,p^4,pq\)\(p,q\) 为不同质数)

首先依次二分判断是不是 \(p^4,p^3,p^2\)。若是,则用map记录p的次数;否则 \(a_i=pq\),丢进vector。

接下来处理所有形如 \(pq\) 的数。先看 \(pq\) 能否被map中的某个素数整除。若不能,看 \(pq\) 与其他 \(p'q'\) 是否有公因数。最后仍有一些 \(pq\) 未能处理,可能有多个 \(a_i\) 相等的情况,得丢进map2中统计。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;
ll n, ans = 1;
map<ll, ll> mp, mp2;
vector<ll> ve;

ll kai(ll x, ll k) //x的k次方(整数)
{
    ll l = 1, r;
    if(k == 2) r = 1414213563; //2e18的平方根上取整
    if(k == 3) r = 1259922; //立方根
    if(k == 4) r = 37607; //四次方根

    while(l < r)
    {
        ll t = 1, m = l + r >> 1;
        for(int i = 1; i <= k; i++) t *= m;
        if(t == x) return m;
        if(t >= x) r = m; else l = m + 1;
    }
    return 0;
}

signed main()
{
    scanf("%lld", &n);
    for(int i = 1; i <= n; i++)
    {
        ll x, sq; scanf("%lld", &x);

        if(sq = kai(x, 4)) mp[sq] += 4;
        else if(sq = kai(x, 3)) mp[sq] += 3;
        else if(sq = kai(x, 2)) mp[sq] += 2;
        else ve.push_back(x);
    }

    for(ll i : ve)
    {
        bool fl = 0;
        for(auto [p,s] : mp)
        {
            if(i % p == 0) {
                mp[p]++, mp[i/p]++;
                fl = 1;
                break;
            }
        }
        if(!fl) for(ll j : ve)
        {
            if(i == j) continue;
            ll g = __gcd(i, j);
            if(g > 1) {
                mp[g]++, mp[i/g]++;
                fl = 1;
                break;
            }
        }
        if(!fl) mp2[i]++;
    }

    for(auto [p,s] : mp) (ans *= (s+1)) %= MOD;
    for(auto [pq,s] : mp2) (ans *= (s+1)*(s+1)) %= MOD;

    printf("%lld", ans);

    return 0;
}

posted @ 2022-01-09 12:51  Bellala  阅读(50)  评论(0)    收藏  举报