传说,这是dfs,其实就是暴搜 + 不暴搜的剪枝。
如我们的n == 21; 那么,我们从个位数1开始搜, 1 * 1 == 1, 9 * 9 == 81,他们的个位数都是1,那么,1和9可以作为我们找的那个数的个位数。
然后我们就记忆一下这个我们找到的东西,放在ans里面。
下面我们开始搜第二位,设搜的是ab的a(其中,我们的b是已经记忆下来的个位)。
ab * ab % 100 = 21; 那么,我们的2 是不是就由(b * b / 10 + a * b * 2) % 10 得到的。于是,我们就for一遍去找a,找到a了,我们就以同样的方法去找c(如果有c的话)。这样,就是剪枝了。
最后,如果我们找的n有x位,那么,我们要找的m * m % ? == n 的m最多也只有x位。至此,就结束了。
解题过程:
WA了一次,因为觉得没必要用__int64的。哎,现在还是觉得没必要,但是就是改成__int64就过了。。。
#include <cstdio>
using namespace std;
__int64 t,digit[20],total,n,ans,remainder,final;
inline __int64 min(__int64 a, __int64 b) {return a > b? b : a;}
void getdigit(__int64 tmp){//得到total = n的位数,digit[]存每个位上分别是什么。
total = 0;
while(tmp){
digit[ ++total] = tmp % 10;
tmp /= 10;
}
}
void solve(__int64 pos, __int64 weight, __int64 ans){
if(total < pos){
final = min(final,ans); return ;//哎,跟线段树一样,又忘记return了。。。
}
for(__int64 k = 0; k < 10; k ++){
if( (ans * ans / weight + remainder * k % 10) % 10 == digit[pos])
solve(pos + 1, weight * 10, k * weight + ans);
}
}
int main(){
scanf("%I64d",&t);
while(t --){
scanf("%I64d",&n);
getdigit(n);
final = 2000000000;
for(__int64 i = 0; i < 10; ++i){
if(i * i % 10 == digit[1]){
remainder = i << 1;
solve(2,10,i);
}
}
if(final == 2000000000)
puts("None");
else
printf("%d\n",final);
}
}

本文探讨使用深度优先搜索(DFS)解决特定数学问题的方法,通过剪枝优化提高效率。详细介绍了从个位数开始搜索,利用已找到的个位数进行剪枝,最终找到符合条件的数的过程。同时,提到了在实现过程中遇到的错误处理,以及通过使用`__int64`类型解决大整数问题的经验。
4万+

被折叠的 条评论
为什么被折叠?



