标签:使用 进制 == 倒序输出 解决 建立 i++ als 超过
题意:给出一个整数n,(1 <= n <= 200)。求出任意一个它的倍数m,要求m必须只由十进制的‘0‘或‘1‘组成,m不超过100位。
解题思路:首先大家应该会想到暴力枚举每一个m,但仔细考虑本题条件应该会涉及处理大数和超时的风险。而使用同余定理就可完全克服这个问题,再仔细分析搜索树就可进一步完全转换存储内容,从根本上解决大数问题。
话不多说,直接上例子,以n=6的bfs搜索过程为例:从最高位开始建立搜索树,逐层搜索每一位
1
0 1
0 1 0 1
0 1 0 1 0 1 0 1
对6求余的结果
1
4 5
4 5 2 3
4 5 2 3 2 3 0 1
即搜索出6的倍数为1110
观察搜索过程,设枚举答案为k(首位一定为1),下一层bfs得到10*k+0,10*k+1
由同余定理知 (10*k+1)%6 = ((10*k)%6 + 1%6) %6=(((10%6)* (k%6))%6 + 1%6)%6
如111%6=3,由同余定理知1110%6 =(111*10+0)%6 =(111%6) * (10%6) + 0)%6
***--------------所以我们只需要存下k对n求余的结果,便可层层bfs搜索了。那就只剩怎么得到真实答案了----------------***
此时想到二叉树的知识,对搜索树的节点从1开始编号
1
2 3
4 5 6 7
8 9 10 11 12 13 14 15
我们发现每一个节点 i 的父节点为 i/2(向下取整),节点编号 i 对2求余的结果即与原搜索树内容相同(i的奇偶性决定该层选1/0)
所以以树形int数组存储k%n,最终从下标 1 到下标 i (mod[i]%n ==0)的搜索路径上每一个下标的奇偶性就得到了最终结果
例:n=6,mod[14] % 6 ==0,搜索路径下标1-3-7-14,最终结果为1-1-1-0
#define _CRT_SECURE_NO_WARNINGS //VS编译器宏 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<math.h> #include<vector> #include<queue> using namespace std; int mod[2000005];//int为4B,给定内存为10000kB,1*10^7B/4B=25*10^5 int main() { int i, n, len; //C语言输入速度快,但加“cin.sync_with_stdio(false);”这行后cin的效率就与scanf相当了 while (~scanf("%d", &n), n) { //相当于while(scanf("%d",&n) != EOF , n) mod[1] = 1 % n; //n为1时直接捕捉 for (i = 2; mod[i - 1]; i++) mod[i] = (mod[i / 2] * 10 + i % 2) % n; i--; //for循环结束条件为mod[i - 1]!=0,真实下标为i-1 len = 0; while (i) { //倒序存储编号 mod[len++] = i % 2; i >>= 1; } while (len--)printf("%d", mod[len]); //倒序输出正确答案 printf("\n"); }
}
POJ - 1426-Find The Multiple-专为小白解惑-同余加搜索树
标签:使用 进制 == 倒序输出 解决 建立 i++ als 超过
原文地址:https://www.cnblogs.com/zsh-notes/p/10500901.html