集训队专题(8)1006 Yet Another Multiple Problem

探讨如何找出不含特定数字的最小正整数倍数,通过BFS算法实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Yet Another Multiple Problem

Time Limit: 40000/20000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5086    Accepted Submission(s): 1141


Problem Description
There are tons of problems about integer multiples. Despite the fact that the topic is not original, the content is highly challenging. That’s why we call it “Yet Another Multiple Problem”.
In this problem, you’re asked to solve the following question: Given a positive integer n and m decimal digits, what is the minimal positive multiple of n whose decimal notation does not contain any of the given digits?
 

Input
There are several test cases.
For each test case, there are two lines. The first line contains two integers n and m (1 ≤ n ≤ 10 4). The second line contains m decimal digits separated by spaces.
Input is terminated by EOF.
 

Output
For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) while Y is the minimal multiple satisfying the above-mentioned conditions or “-1” (without quotation marks) in case there does not exist such a multiple.
 

Sample Input
  
2345 3 7 8 9 100 1 0
 

Sample Output
  
Case 1: 2345 Case 2: -1
 

Source
 

此题题意就是说给你一个数n,然后再给你m个数字,问你最小的不含着m个数字的n的倍数,这题很容易想到的就是从高位到低位,从小数到大树的方法进行一一枚举,这样枚举出来先得到的一定是最小的,但是那么问题来了,怎么进行判定没有结果呢,显然,如果不对没有结果这种结果进行处理的话一定会陷入一个死循环内,我们一定要对其进行判定,这时此题就摇身一变,从一个暴力题变成了一个数论题(好吧,其实这题本来就是一个数论题),接下来小编就要给出这个数论题的推导过程了(数论题最重要的不是思路,而是推导过程对吧~)。

设k,i是两个常数,A=k*B+C(即A%B=C),则:

1.(A+i)%B = C+i%B

2.(A*i)%B = (C*i)%B

证明到这里你可能会问小编……跟这题有什么关系,额…这个嘛,确实没什么关系(害怕……),但是上面两个式子直观的给我们展示了一个道理,那就是对一个数进行处理后对某个数的取模值,相当于是对其处理前的取模值进行处理。接下来小编给出关键的证明过程。

设k1,k2,i是两个常数,A1=k1*B+C(即A1%B=C),A2=k2*B+C(即A2%B=C),则:

1.(A1+i)%B = (A2+i)%B = C+i%B

2.(A1*i)%B = (A2*i)%B = (C*i)%B

如果两个数对某个数的取模相等,那么对他们进行相同的处理,得到的结果是一样的(绕了这么大的圈终于到重点了),也就是说如果我们子啊进行处理的时候遇到两个数对某个数的取模相等的话,就可以跳过这个条件,会到题目,这下你可能会知道什么时候会没有结果了吧,那就是当我们队某个数的取模的所有值全部情况都遍历到了(比如对n取模,0~n-1的情况都出现过了),而没得到结果的话,那就说明这种情况是没有结果了。遍历的过程我们就运用BFS来实现吧

#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;
const int N = 1e4+5;
bool vis[N],del[10];
int n,pre[N];
char ans[N];
bool bfs()
{
	queue<int> Q;
	Q.push(0);
	while(!Q.empty())
	{
		int cur = Q.front();
		Q.pop();
		for(int i=0; i<10; i++)
		{
			if(del[i] || cur==0&&i==0)
				continue;
			int next = (cur*10+i) % n;
			if(vis[next]) continue;
			ans[next] = '0'+i;
			vis[next] = true;
			pre[next] = cur;
			Q.push(next);
			if(next == 0) return true; 
		}
	}
	return false;
}
void solve()
{
	string res;
	int p = 0;
	while(p!=0 || res.empty())
	{
		res += ans[p];
		p = pre[p];
	}
	reverse(res.begin(),res.end());
	puts(res.c_str());
}
int main()
{
	int m,T=0;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(vis,0,sizeof(vis));
		memset(del,0,sizeof(del));
		while(m--)
		{
			int k;
			scanf("%d",&k);
			del[k] = true;
		}
		printf("Case %d: ",++T);
		if(bfs()) solve();
		else printf("-1\n");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值