算法 - 短除法与回文


题目:ACwing 1346. 回文平方

题目来源:https://www.acwing.com/problem/content/1348/

描述:

回文数是指数字从前往后读和从后往前读都相同的数字。

例如数字 12321 就是典型的回文数字。

现在给定你一个整数 B,请你判断 1∼300 之间的所有整数中,有哪些整数的平方转化为 B 进制后,其 B 进制表示是回文数字。

输入格式
一个整数 B。

输出格式
每行包含两个在 B 进制下表示的数字。

第一个表示满足平方值转化为 B 进制后是回文数字那个数,第二个数表示第一个数的平方。

所有满足条件的数字按从小到大顺序依次输出。

数据范围
$2≤B≤20,$
对于大于 9 的数字,用 A 表示 10,用 B 表示 11,以此类推。

输入样例:

1
10

输出样例:

1
2
3
4
5
6
7
8
9
10
11
12
1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
264 69696

算法1:$O(n)$

回文:
利用双指针,一个指针在前,一个指针在后,然后如果向两边靠拢,如果不等返回flase

1
2
3
4
5
6
7
bool check(string s)
{
for(int i = 0, j = s.size() - 1; i < j; i++, j--)
if (s[i] != s[j])
return false;
return true;
}

短除法:
n / b等到余数,当 n / b = 0 的时候停止,最后余数的余数倒着写。
如:

123 / 7 = 17 … 4
17 / 7 = 2 … 3
2 / 7 = 0 … 2

所以 123的 7 进制为234 = $2 * 7^2 + 3 * 7^1 + 4 * 7^0 = 49 * 2 + 21 + 4 = 123$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <algorithm>

using namespace std;
int b;

bool check(string s)
{
for(int i = 0, j = s.size() - 1; i < j; i++, j--)
if (s[i] != s[j])
return false;
return true;
}

// 转化为B进制, 如果大于10 用ABC....来替换
char get(int n)
{
if (n <= 9) return n + '0';
return 'A' + n - 10;
}

string base(int n, int b)
{
string res;
while(n) res += get(n % b), n /= b;
reverse(res.begin(), res.end());
return res;
}

int main()
{
cin >> b;

for(int i = 1; i <= 300; i++)
{
string s = base(i * i, b);
if (check(s))
{
cout << base(i, b) << ' ' << s << endl;
}
}
return 0;
}