ural 1698. Square Country 5(记忆化搜索)

1698. Square Country 5

Time limit: 2.0 second
Memory limit: 64 MB
The first arithmetical operation taught to the children of the Square country is the calculation of squares of positive integers. At the first lesson the children are provided with “easy” numbers, calculating a square of which can be done by writing a few digits in front of them (i.e. 76 is an easy number because 762 = 5776). Of course, the numbers cannot contain leading zeroes. The task shouldn't be too difficult, so the easy numbers shouldn't contain more than n digits. How many different easy numbers can teachers prepare for the first lesson?

Input

The only input line contains an integer n (1 ≤ n ≤ 2000), the maximal length of the easy number the children can be provided with.

Output

Output the number of different easy numbers consisting of at most n digits.

Sample

inputoutput
1
3

题意:

方块国的孩子们学到的第一个算术运算是正整数的平方计算.孩子们首先学的是那些"简单"数字的平方计算.所谓简单数字就是那些只需要在原数后加几个数字就可得到原数平方的数字(例如,76是简单数字,因为762=5776).当然,所有`数字都不能包含前导0.平方运算不能太麻烦,所以简单数字都不能超过n位.老师们总共可以准备多少简单数字?

输入

只有一个数字n(1<=n<=2000),表示给孩子们的简单数字的最大长度.

输出

输出不超过n位的简单数字个数.

[编辑]样例

[编辑]样例输入

1

[编辑]样例输出

3

思路:

进行记忆化搜索,利用大数乘的方法,寻找自守数;

前道知识:

如果某个数的平方的末尾几位数等于这个数,那么就称这个数为自守数。
显然,5和6是一位自守数(5x5=25 6x6=36)
25x25=625 76x76=5776,所以25和76是两位自守数。
自守数有一个特性,以他为后几位的两个数相乘,乘积的后几位仍是这个自守数。因为5时自守数,所以以5为个位数的两个数相乘,乘积的个位仍然是5;76是自守数,所以以76为后两位数的两个数相乘,其结果的后两位仍是76,如176x576=101376。
虽然0和1的平方的个位数仍然是0和1,但是他们太“平凡”了,研究他们没有意义,所以不算自守数。
三位自守数是625和376,四位自守数是0625和9376,五位自守数是90625和09376......
我们可以看到,(n+1)位的自守数出自n位的自守数。由此得出,如果知道n位的自守数a,那么(n+1)位的自守数应当由a前面加上一个数构成。
实际上,简化一下,还能发现如下规律:
5+6=11
25+76=101
625+376=1001
......
所以,两个n位自守数,他们的和等于10^n+1
 
代码:
 1 #include <iostream>
 2 #include <string>
 3 #include<cstring>
 4 #include <queue>
 5 #include <vector>
 6 #include <map>
 7 #include <algorithm>
 8 #include <cmath>
 9 #include <cstdio>
10 
11 
12 
13 using namespace std;
14 int n, ans;
15 int a[2005];
16 int b[2005];
17 
18 
19 
20 bool check(int k)
21 {//计算平方后的第k+1位的数值;
22     b[k] = 0;
23     for (int i = 0; i <= k; ++i)
24         b[k] += a[i] * a[k - i];
25     if (k)
26         b[k] += b[k - 1] / 10;
27     return b[k] % 10 == a[k];
28 }
29 
30 void dfs(int k)
31 {
32     if (k >= n)
33         return;
34     for (int i=9;i>=0;--i)
35     {
36         a[k] = i;
37         if (check(k))
38         {
39             if (a[k])
40             {//第k+1位数不是0,表示产生了新的自守数;
41                 ans++;
42             }
43             dfs(k + 1);
44         }
45     }
46 }
47 
48 
49 
50 int main()
51 {
52     scanf("%d", &n);
53     dfs(0);
54     printf("%d
", ans);
55 }
View Code
原文地址:https://www.cnblogs.com/zhangchengbing/p/3426593.html