CF538B Quasi Binary 思維題

liuchanglc發表於2020-10-07

題目描述

給出一個數 \(n\),你需要將 \(n\) 寫成若干個數的和,其中每個數的十進位制表示中僅包含\(0\)\(1\)

問最少需要多少個數

輸入輸出格式

輸入格式:

一行 一個數 \(n(1≤n≤10^6)\)

輸出格式:

最少的數的個數,並給出一種方案。

輸入輸出樣例

輸入 #1

9

輸出 #1

9
1 1 1 1 1 1 1 1 1

輸入 #2

32

輸出 #2

3
10 11 11

分析

很顯然,對於任何一個數,我們把它分成只包含 \(0\)\(1\) 的數字,這樣的最小劃分數一定不大於 \(9\)

因此在劃分的過程中一定不會出現借位的情況

因為如果出現借位的情況,那麼要想把借的那一位消去,至少需要 \(10\) 次操作

所以對於當前的數,我們可以存一下每一位能劃分出多少 \(1\)

然後按照劃分出 \(1\) 的個數從小到大排一下序

如果當前的個數不為 \(0\),那麼我們就從當前這一位開始一直到最後都減去當前的個數

這樣到最後,所有位上的數量都會變成 \(0\)

分析

#include<cstdio>
#include<algorithm>
const int maxn=15;
struct asd{
	int num,id;
	asd(){}
	asd(int aa,int bb){
		num=aa,id=bb;
	}
}b[maxn];
bool cmp(asd aa,asd bb){
	return aa.num<bb.num;
}
int n,cnt,sta[maxn],top;
int main(){
	scanf("%d",&n);
	int cs=1;
	while(n){
		b[++cnt]=asd(n%10,cs);
		n/=10;
		cs*=10;
	}
	std::sort(b+1,b+1+cnt,cmp);
	int head=1;
	while(head<=cnt){
		int now=0;
		while(b[head].num==0 && head<=cnt) head++;
		for(int i=head+1;i<=cnt;i++){
			now+=b[i].id;
			b[i].num-=b[head].num;
		}
		now+=b[head].id;
		for(int i=1;i<=b[head].num;i++){
			sta[++top]=now;
		}
		b[head].num=0;
	}
	printf("%d\n",top);
	for(int i=1;i<=top;i++){
		printf("%d ",sta[i]);
	}
	printf("\n");
	return 0;
}

相關文章