51nod1385 凑数字

本文探讨了如何找出包含1到n所有整数的最短字符串S,并详细解释了求解该问题的方法与思路,包括构造算法及证明过程。

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

1385 凑数字

给定一个n,要求找出一个最短的字符串S,使得所有1到n的整数都是S的子序列。

比如n=10,那么S=”1234056789”的时候,是满足条件的。这个时候S的长度是10。

 

现在给出一个n,要求输出最短S的长度。

Input
第1行:给出一个整数n (1<=n<=1e10000)。
Output
输出最短S的长度
Input示例
10
Output示例

    10

  


题解:orz真是强无敌。。。

f(n)表示最短S的长度。

那么首先f(n)>=f(n-1),这是为什么呢?

反证法,假如f(n)<f(n-1)那么f(n)的时候他的S是可以表示1n-1的所有数字的,那么f(n-1)明显可以取到f(n)的,所以与f(n-1)是最小值矛盾,f(n)>=f(n-1).

f(n)的时候可以表示1n的数字。那么在这个串中每一种数字至少要有len(n)-1个。

Len(n)表示n的十进制长度。

而每一种数字在1n中出现次数最多的可能是len(n).

最后答案是每一种数字在1n中出现次数最多的加起来。

下面证明一下,

构造串的时候可以这样构造,先每一种数字拿出len(n)-1个,然后按照以下顺序排列

9876543210*(len(n)-1).

那么剩下的数字记为R就放在开头。这个时候对于以剩下数字开头的数字且长度==len(n)的是非常好表示的。但是那些开头不在R里面的怎么办呢?

这个时候要表示的数字的形状是这样的子的

先找到最小的k,使得前面k位相等,然后到k+1位,b(k+1)<b(k)

所以这儿第k堆的9876543210里面有两个或以上的数字可以利用了。

这样也是能够构造出len(n)长度的数字。

为什么这样是最少的呢?

这个是因为串中每一种数字出现的次数是取1n中出现次数最多,如果某个数字少一个,肯定表示不了其中一个数字。所以是最少的。

总的计算复杂度是O(len(n))



代码:

#include<bits/stdc++.h>
using namespace std;
int m,i,j,ans,a[100002],p;
char s[100002];
int main(){
	scanf("%s",&s);
	m=strlen(s);
	for(i=0;i<m;i++)
	 a[i+1]=s[i]-'0';
	for(i=9;i;i--){
		p=0;
		for(j=1;j<=m;j++)
		{
			if(a[j]<i){
				p=1;
			break;}
			if(a[j]>i){
				break;
			}
		}
		if(!p){
			ans=i;
			break;
		}
	}
	printf("%d",ans+(m-1)*10);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值