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

浙公网安备 33010602011771号