链接:https://ac.nowcoder.com/acm/contest/3002/E
题目描述
rin最近喜欢上了数论。
然而数论实在太复杂了,她只能研究一些简单的问题。
这天,她在研究正整数因子个数的时候,想到了一个“快速迭代”算法。设 f(x) 为 x 的因子个数,将 f(x) 迭代下去,rin猜想任意正整数最终都会变成 。
例如:f(12) = 6, f(6) = 4, f(4) = 3, f(3) = 2 。
她希望你帮她验证一下。她会给你一个正整数 n,让你输出它在迭代过程中,第一次迭代成 2 的迭代次数。
输入描述:
一个正整数 n (3 <= n <= 10^12)
输出描述:
一个正整数,为 n 迭代至 2 的次数。
示例
输入
12
输出
4
说明
12的因子:1,2,3,4,6,12。共6个。
6的因子:1,2,3,6。共4个。
4的因子:1,2,4。共3个。
3的因子:1,3。共2个。
12 → 6 → 4 → 3 → 2 , 故迭代了4次。
搬运
唯一分解定理
一个数n肯定能被分解成 . 因为一个数肯定是由合数和质数构成的,合数又可以分解成质数和合数,最后递归下去就会变成质数的乘积。比如36 -> 223*3 -> 2^2 * 3^2 .
最后化成了质数相乘的形式。
其中 (2)中运用等比数列求和公式可化简为:
本题可以应用公式: n的因子个数 = (1+a1)(1+a2)…(1+an)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <math.h>
#include <map>
using namespace std;
typedef long long ll;
ll cnt(ll n) //求 n 的因子个数
{
ll i, ans = 1, a;
for(i = 2; i*i <= n; i++)
{
if(n%i == 0)
{
a = 0;
while(n%i == 0)
{
n /= i;
a++;
}
ans *= (a+1);
}
}
if(n > 1)
ans *= 2;
return ans;
}
int main()
{
ll n, i, tmp;
while(~scanf("%lld", &n))
{
tmp = cnt(n);
i = 1;
while(tmp != 2)
{
tmp = cnt(tmp);
i++;
}
printf("%lld\n", i);
}
return 0;
}
cnt()函数看的大神的代码,真是个神奇的写法,一开始还不懂为什么 “if(n > 1) ans *= 2; ” ,觉得最后一定有 n == 1, 所以输出中间过程看了一下(如下图),发现原来不是啊。比如520 = 2^3 * 5^1 * 13^1, 所以在素数13的那层循环里,找不到的n%i == 0, 13的指数 1 就要放到最后去乘
当然,函数的部分也可以直接放在main()里, 用一个while 循环
int main()
{
ll n, i, ans, a;
int cnt;
while(~scanf("%lld", &n))
{
cnt = 0;
while(n != 2)
{
cnt++;
ans = 1;
for(i = 2; i*i <= n; i++)
{
if(n%i == 0)
{
a = 0;
while(n%i == 0)
{
n /= i;
a++;
}
ans *= (a+1);
}
}
if(n > 1)
ans *= 2;
n = ans;
}
printf("%d\n", cnt);
}
return 0;
}
然后,求因子个数还可以
ll cnt(ll n)
{
ll i, ans;
ans = 0;
for(i = 1; i*i <= n; i++)
if(n%i == 0)
ans += 2;
i--;
if(i*i == n)
ans--;
return ans;
}
显然这是一个伪原创,参考多方文章,但对这个题不好说是转载,就投了原创(捂脸),如有侵权,及时联系