传送门
给出(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
", ans);
}