Codeforces 915 C Permute Digits (思维)解题报告

C. Permute Digits
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given two positive integer numbers a and b. Permute (change order) of the digits of a to construct maximal number not exceeding b. No number in input and/or output can start with the digit 0.

It is allowed to leave a as it is.

Input

The first line contains integer a (1 ≤ a ≤ 1018). The second line contains integer b (1 ≤ b ≤ 1018). Numbers don't have leading zeroes. It is guaranteed that answer exists.

Output

Print the maximum possible number that is a permutation of digits of a and is not greater than b. The answer can't have any leading zeroes. It is guaranteed that the answer exists.

The number in the output should have exactly the same length as number a. It should be a permutation of digits of a.

Examples
input
123
222
output
213
input
3921
10000
output
9321
input
4940
5000
output
4940

题目描述:给定两个数a和b,求将a每一位重新排列后不大于b的最大的数是多少。

思路:一开始想暴力,结果看到数据1e18,肯定要超时。然后想了一下。一开始可以把a的每一个数字对应的个数用数组存起来,如果b的位数大于a的位数,我们找的答案只要把数字从大到小放在位数从高到低的位置。

如果b的位数等于a的,我们就从高位到低位逐一枚举,每个位都填小与等于b的该位的数字。这里要注意如果有一位枚举的数小与b对应的位的数字,剩下的每个位就直接找最大的数字填入就好了。如果有一位没有找到小于等于该位的数字,就退一位,把那一位的数字减小,一直没找到就一直退位重新匹配。这也是代码里出现那个while循环的原因。

(当初一直在某一位为0这个问题上纠结。其实因为题中提到了,答案一定存在,那么如果某一位为0,我们要么肯定能匹配为0,要么前面的高位已经小与对应的位了,0对应的位我们只要匹配上最大的数就好了。)

每次都啰嗦半天···上代码——

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char s1[20],s2[20];
typedef long long ll;
ll x,y;
bool flag;
int a[11],b[20],ans[20];
int Find(int t)
{
	int i;
	if(flag==false)
	for(i=t;i>=0;i--)
	{
		if(i<=t&&a[i]!=0)
		return i;
	}
	if(flag==true)
	{
		for(i=9;i>=0;i--)
		{
			if(a[i]!=0)
			return i;
		}
	}
	return -1;
}
void solve()
{
	int i,j,t,n1,n2;
	flag=false;
	memset(a,0,sizeof(a));
	n1=strlen(s1);
	n2=strlen(s2);
	for(i=0;s1[i];i++)
	a[s1[i]-'0']++;
	for(i=0;s2[i];i++)
	b[i]=s2[i]-'0';
	
	if(n2==n1)
	{
		for(i=0;i<n2;i++)
		{
			t=Find(b[i]);
			if(t!=-1)
			{
				ans[i]=t;
				if(t!=b[i])
				flag=true;
				a[t]--;
			}
			if(t==-1)
			{
				while(t==-1)
				{
					i--;
					a[ans[i]]++;
					t=Find(b[i]-1);
				}
				ans[i]=t;
				a[t]--;
				flag=true;
			}
		}
	}
	if(n2>n1)
	{
		for(i=0;i<n1;i++)
		{
			t=Find(9);
			ans[i]=t;
			a[t]--;
		}
	}
	for(i=0;i<n1;i++)
	cout<<ans[i];
	cout<<endl;
}
int main()
{
	while(cin>>s1>>s2)
	{
		solve();
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值