ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

51nod 01组成的N的倍数 题解

2022-02-02 15:33:07  阅读:214  来源: 互联网

标签:11 10 01 剪枝 51nod 题解 拓展 int


前言
发现一道好题目。题目广搜,需要绝妙的数学证明与剪枝,思维含量较大,搜索玩出花来。
若在比赛中肯定想不出正解(话说这篇题解也不是最优解)。我的数学太弱了……抽屉原理都不知道……
看题解吧: )


题目

给定一个自然数N,找出一个M,使得M>0且M是N的倍数,并且M的10进制表示只包含0或1。求最小的M。
例如:N = 4,M = 100。
输入
输入1个数N。(1≤N≤106)
输出
输出符合条件的最小的M。
输入样例
4
输出样例
100


题解

首先对M存在进行证明。
考虑数列:1,11,111,…,11…11(N个1)。由抽屉原理知其中要么有数能被N整除,要么有两个数除N同余。若有数能整除,命题显然成立;若有两数除N同余,用大数减去小数,得到的数形如11…10…00,,能被N整除,命题也成立。
接着搜索构造M。最开始的数为1,每次考虑在原数的末尾加上0或1,按照此法进行搜索,当构造的数%N==0时,即为答案。此处搜索要用广搜,因为广搜可以保证搜到的第一个数一定是最小的。
显然,如此搜索需要剪枝。这里给出剪枝的方法是:若有两个构造得到的数x,y,不妨设x<y。如果x%N=y%N,那么y不必继续拓展。
证明。设x=k1n+r,y=k2n+r。x拓展得到的数x1=10k1n+10r,x2=10k1n+10r+1,y拓展得到的数为y1=10k2n+10r,y2=10k2n+10r+1。可以发现,x1%n=y1%n,x2%n=y2%n。于是得到,x拓展到答案的步数与y拓展到答案的步数相等。那么y显然不可能成为最佳答案,我们只需要拓展较小的数x即可。
具体实现时,只需不断标记x%n,之后若拓展得到的y%n已经被标记,那么continue。
但又有另一个问题:M可能极大,超出long long的范围,高精度又太慢,那该如何记录构造出的数呢?
注意到,数x到答案的步数只与x除n的余数r有关(可以从上文x拓展得到的x1与x2除n的余数证明)。再看上文剪枝的方法,发现:每个除n的余数只对应单独一个构造的数。那么我们可以以余数r为下标,记录对应的数的构造路径(例如101由10拓展得,那么101的r指向10的r)。输出时一路往前回指,递归输出即可。
此解针对的数据规模为N≤106,此题的进阶版N≤109需要更强大的算法,我也不会……

Code

#include<cstdio>
#include<queue>
using namespace std;
const int N = 1e6 + 10;
struct node {
	int bit, pre;
} path[N];
int n;
bool vis[N];
queue<int> q;
void bfs() {
	int x, y;
	path[1] = (node){1, -1};
	vis[1] = 1;
	q.push(1);
	while (!q.empty()) {
		x = q.front(); q.pop();
		if (x == 0) return ;
		for (int i = 0; i <= 1; i++) {
			y = (x * 10 + i) % n;
			if (!vis[y]) {
				path[y] = (node){i, x};
				vis[y] = 1;
				q.push(y);
			}
		}
	}
}
void Print(int x) {
	if (path[x].pre != -1) Print(path[x].pre);
	printf("%d", path[x].bit);
}
int main() {
	scanf("%d", &n);
	bfs();
	Print(0);
	printf("\n");
	return 0;
}

标签:11,10,01,剪枝,51nod,题解,拓展,int
来源: https://www.cnblogs.com/Fisher-Y/p/15860378.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有