目录
数论里面有各种有趣的数。
一,完全数
1,完全数
如果一个大于1的正整数的所有因子之和等于它的本身,则称这个数是完全数,比如6,28都是完全数:6=1+2+3;28=1+2+4+7+14。
(1)计算机求解
利用模板很容易求出1亿之内的完全数:
int main() {
for (int i = 1; i <= 100000000; i++) {
auto v = GetDivisors(i);
int s = 0;
for (auto x : v)s += x;
if (s == i*2)cout << i << " ";
}
return 0;
}
求出1亿之内只有5个完全数:6, 28, 496, 8128, 33550336
(2)数学求解
偶完全数很好求,因为欧拉求出了所有的偶完全数,它们有共同的表达式:
t*(t-1)/2,其中t=2^p,满足p为素数且t-1为素数
奇完全数还没有定论,如果存在的话,最小的奇完全数也一定很大。
2,OJ实战
HDU 1406 完数
题目:
完数的定义:如果一个大于1的正整数的所有因子之和等于它的本身,则称这个数是完数,比如6,28都是完数:6=1+2+3;28=1+2+4+7+14。
本题的任务是判断两个正整数之间完数的个数。
Input
输入数据包含多行,第一行是一个正整数n,表示测试实例的个数,然后就是n个测试实例,每个实例占一行,由两个正整数num1和num2组成,(1<num1,num2<10000) 。
Output
对于每组测试数据,请输出num1和num2之间(包括num1和num2)存在的完数个数。
Sample Input
2
2 5
5 7
Sample Output
0
1
代码:
#include<iostream>
using namespace std;
int main()
{
int a, b;
cin >> a;
while (cin >> a >> b)cout << ((a - 6)*(b - 6) <= 0) + ((a - 28)*(b - 28) <= 0) + ((a - 496)*(b - 496) <= 0) + ((a - 8128)*(b - 8128) <= 0) << endl;
return 0;
}
这个代码,自然是0ms AC了
因为写的时候a和b是对称的,所以不需要额外判断a和b的大小
力扣 507. 完美数
对于一个 正整数,如果它和除了它自身以外的所有 正因子 之和相等,我们称它为 「完美数」。
给定一个 整数 n
, 如果是完美数,返回 true
;否则返回 false
。
示例 1:
输入:num = 28 输出:true 解释:28 = 1 + 2 + 4 + 7 + 14 1, 2, 4, 7, 和 14 是 28 的所有正因子。
示例 2:
输入:num = 7 输出:false
提示:
1 <= num <= 108
class Solution {
public:
bool checkPerfectNumber(int num) {
return num==6||num==28||num==496||num==8128||num==33550336;
}
};
二,快乐数
A happy number is defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers, while those that do not end in 1 are unhappy numbers (or sad numbers).
一个数的所有数字的平方和,替换这个数本身,一直循环这个过程,如果最后能变成1那么就是Happy Number
首先,很显然,经过几次替换之后就会得到一个小于200的整数,
然后找规律,我们发现不是快乐数的数都会陷入同一个循环,循环里面最小的数是4,我们用程序验证一下:
#include<iostream>
using namespace std;
int f(long long n)//求平方和
{
if (n == 0)return 0;
return f(n / 10) + (n % 10)*(n % 10);
}
int main()
{
for(int i=1;i<200;i++){
int n=i;
while(n!=1&&n!=4)n=f(n);
cout<<n<<" ";
}
return 0;
}
可以发现有32个1和167个4
力扣 202. 快乐数
题目:
编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
示例:
输入: 19
输出: true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
思路:
首先,很容易发现,所有的数经过若干次变换之后就最多三位数,而且不管再怎么变换都是最多三位数。
所以,所有的数最后都会进入循环。
其次,很容易发现,若干次变换之后一定会不超过162,而且不管再怎么变换都不超过162
只要枚举1到162经过若干次变换之后变成多少就行了。
结果是2个集合,一个是1,一个是{4,16,37......}
所以,所有的数经过若干次变换之后都会变成1或4
代码:
class Solution {
public:
bool isHappy(int n) {
if (n == 4)return false;
if (n == 1)return true;
int ans = 0;
while (n)
{
ans += n % 10 * (n % 10);
n /= 10;
}
return isHappy(ans);
}
};
三,平方和
力扣 633. 平方数之和
给定一个非负整数 c
,你要判断是否存在两个整数 a
和 b
,使得 a2 + b2 = c
。
示例 1:
输入:c = 5 输出:true 解释:1 * 1 + 2 * 2 = 5
示例 2:
输入:c = 3 输出:false
提示:
0 <= c <= 231 - 1
class Solution {
public:
bool judgeSquareSum(int c) {
return Facs::isSquareSum(c);
}
};