HDU 4294 Multiple(12年成都)

转载请注明出处,谢谢http://blog.youkuaiyun.com/acm_cxlove/article/details/7854526       by---cxlove

题目:在K进制下,用最少的不同的数,表示成n的倍数

http://acm.hdu.edu.cn/showproblem.php?pid=4294 

首先要得到一个结论,就是最多用两个数就行了。

证明 :对于一个数字a,可以构造出的数字有

a,aa,aaa,aaaa,aaaaa,……

每一个数对于n都有一个余数,余数最多有n个,根据鸽巢原理,前n+1个数中,必然有两个余数相等

那么二者之差,必定为n的倍数,形式为a……a0……0。

有这个结论,就简单了

先枚举一个数,然后枚举两个数,BFS即可

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1<<28
#define M 100005
#define N 50005
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define MOD 1000000007
using namespace std;
int num[2],m,step[N],pre[N];
int n,c,ope[N];
string s,ans;
bool bfs(){
	queue<int>que;
	mem(step,0);
	for(int i=0;i<m;i++){
		if(!num[i]||step[num[i]%n]) continue;
		pre[num[i]%n]=-1;
		step[num[i]%n]=1;
		ope[num[i]%n]=num[i];
		que.push(num[i]%n);
	}
	while(!que.empty()){
		int u=que.front();
		que.pop();
		if(u==0) return true;
		if(ans.size()&&step[u]>ans.size()) return false;
		for(int i=0;i<m;i++){
			int v=(u*c+num[i])%n;
			if(!step[v]){
				step[v]=step[u]+1;
				ope[v]=num[i];
				pre[v]=u;
				que.push(v);
			}
		}
	}
	return false;
}
void slove(int k){
	if(pre[k]!=-1) slove(pre[k]);
	s+=(char)(ope[k]+'0');
}
bool cmp(string a,string b){
	if(b.size()==0) return true;
	if(a.size()>b.size()) return false;
	if(b.size()>a.size()) return true;
	return a<b;
}
int main(){
	while(cin>>n>>c){
		bool flag=false;ans="";
		for(int i=1;i<c;i++){
			num[0]=i;m=1;
			if(bfs()){
				flag=true;
				s="";
				slove(0);
				if(cmp(s,ans))
					ans=s;
			}
		}
		if(!flag){
			for(int i=1;i<c;i++){
				for(int j=0;j<i;j++){
					num[0]=j;num[1]=i;m=2;
					if(bfs()){
				    	s="";
						slove(0);
						if(cmp(s,ans))
							ans=s;
					}
				}
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值