cf 1033 D. Divisors - 假的rho + 质因子 - 挺有意思的数论题

传送门
给出\(n\)个数字,然后把这\(n\)个数字相乘,求最后数字的约数个数
\(n\)个数每个数字的约数个数是\([3,5]\)

看了一眼,哟吼,rho啊,把数字质因子分解,然后答案就是\(\prod_{i = 1}^m(cnt_i+1)\) 交了一发,tle了。

仔细看,一个数的约数个数是\([3,5]\),那么有这么几种可能

  • \(a * b\)
  • \(a^b\)
  • \(a^3\)
  • \(a^4\)

其中\(a,b\)都是质数
后三种比较好判断,直接开根号就行了,对于第一种情况。
我们用两个map,一个用于统计质因子的个数,另一个也就说第一种情况。

按照公式来说,必须把所有出现过的质因子放一起计算,也就说样例1的15,如果说不能分解为后三种情况,那么也就是第一种情况。15是两个质数的乘积。那么按照公式,需要把3的幂加1,那么也就是说我们取遍历一下,找到15和其他数字是否存在gcd,如果存在,那边gcd就是其中一个质数,就需要进行统计,放进第一个map里面。而对于没有gcd的情况。就直接记录到第二个map里面,因为这个数字的两个质因子肯定没有出现过,那么按照公式就相当于直接乘4就行了。

std::map<ll, int> mp;
std::map<ll, int> mp2;
ll aa[1000];
int nn;
ll cal(ll x){
    ll n = x;
    ll a = pow(n, 1.0 / 2) - 1, b = pow(n, 1.0 / 3) - 1, c = pow(n, 1.0 / 4) - 1;
    while(qpow(a, 2) < n) a++;
    while(qpow(b, 3) < n) b++;
    while(qpow(c, 4) < n) c++;
    if(qpow(c, 4) == n) return mp[c] += 4;
    if(qpow(b, 3) == n) return mp[b] += 3;
    if(qpow(a, 2) == n) return mp[a] += 2;
    for(int i = 1; i <= nn; i++) {
        ll g = gcd(n, aa[i]);
        if(g != 1 && aa[i] != n)  {
            return mp[n / g]++, mp[g]++;
        }
    }
    return mp2[n]++;
}
void solve(int kase){
    cin >> nn;
    for(int i = 1; i <= nn; i++) {
        scanf("%lld", &aa[i]);
    }
    for(int i = 1; i <= nn; i++) cal(aa[i]);
    ll ans = 1;
    
    for(auto xx : mp) {
        ans = ans * (xx.second + 1) % CM;
    }
    for(auto xx : mp2) {
        ans = ans * (xx.second + 1) * (xx.second + 1) % CM;
    }
    printf("%lld\n", ans);
}
posted @ 2021-01-16 14:38  Emcikem  阅读(87)  评论(0编辑  收藏  举报