UVA10527 Persistent Numbers 贪心+高精度除法

2 篇文章 0 订阅
1 篇文章 0 订阅

UVA10527 Persistent Numbers

简要题意

每行输入一组数据,包含一个数,试求一个数,使该数满足其各位的乘积等于输入的数且该数的值在所有满足以上条件的数中最小. 输入以单独的一个-1结束. 保证输入的数的位数不超过1000位,输出的数的位数不超过3000位. 如果对于某一组数据,没有任何满足条件的数存在,则输出“There is no such number.”

题目分析

不妨首先假设这个数存在. 思考:在什么情况下所求数最小呢?可以发现,首先要数位最小,其次要数位的数由高数位到低数位升序排列. 分析可知我们可以使用贪心. 那么我们就可以得到以下的贪心思路:

由9到2进行for循环,
若输入的数能被k个i整除,
则将这k个i放到输出队列的末尾,并输入除以k*i;
当输入只剩下一位时,就可以按顺序输出结果了.

接下来我们考虑数不存在的情况,可以发现,如果输入仍然大于9且不能被2~9的任何一个数整除,则该组数据无解.

还有一个问题:输入的数最多能达到1000位,输出最多能达到3000位. 所以我们需要使用高精度算法.

以下是高精除以低精的模板.

#include<bits/stdc++.h>
using namespace std;
int b,a[100],c[100],x;
string ch;
int main(){
	cin>>ch;
	cin>>b;
	int lena=ch.length();
	for(int i=0;i<lena;i++){
		if(isdigit(ch[i]))a[i+1]=ch[i]-'0';
	}
	for(int i=1;i<=lena;i++){
		c[i]=(x*10+a[i])/b;
		x=(x*10+a[i])%b;//按位相除
	}
	int lenc=1;
	while(c[lenc]==0&&lenc<lena)lenc++;//删除前导零
	for(int i=lenc;i<=lena;i++)cout<<c[i];
	cout<<endl;
	return 0;
}

而高精除以高精是用减法模拟除法,对被除数的每一位(这里的“一位”包含前面的余数,下同)都减去除数,一直减到这一位小于除数为止,实现会另讲.

程序实现

#include<bits/stdc++.h>
#define maxn 1010
using namespace std;
char str[maxn],ans[maxn];
int num[3*maxn];
bool count(int i){
	int mod=0,k=0;
	char *q;
	for(int j=0;isdigit(str[j]);j++){
		mod=mod*10+str[j]-'0';
		ans[k++]=mod/i+'0';
		mod%=i;
	}
	ans[k]='\0';
	q=ans;
	while(*q=='0')q++;
	if(mod!=0)return false;
	int h=0;
	for(h=0;isdigit(*q);h++,q++){
		str[h]=*q;
	}
	str[h]='\0';
	return true;
}
int main(){
	while(scanf("%s",str),str[0]!='-'){
		int k=0;
		if(!isdigit(str[1])){
			cout<<"1"<<str<<endl;
			continue;
		}
		for(int i=9;i>1;i--){
			while(count(i)){
				num[k++]=i;
			}
		}
		if(strlen(str)>1){
			printf("There is no such number.\n");
			continue;
		}
		while(k>0)printf("%d",num[--k]);
		printf("\n");
	}
	return 0;
}

本题总结

1. 1. 1.对于贪心,想的不多,思考方向不正确,应该从结论入手,考虑什么时候最小.

2. 2. 2.高精度不会写,导致很多题就算会了也拿不到分,令人遗憾.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值