课外练习【循环之后】D: Gakki的疑问

在新垣结衣(Gakki)的生日之际,她的丈夫姚师姐面临了一个有趣的数学挑战:将任意数字分解为最少数量的由0和1组成的漂亮数之和。本文详细解析了解题思路与算法实现,通过巧妙的位操作和数字处理,实现了高效的求解。

问题 D: Gakki的疑问

题目描述

众所周知,新垣结衣(Gakki)很爱她的老公姚师姐,6月11日是Gakki的生日,姚师姐想送她生日礼物,于是跑去问:“老婆,你最近缺些什么吗?”,可爱的Gakki很傲娇,她拿起笔在纸上写了写,然后羞涩地塞给师姐,说:“这道题,你能在1s里解出来,就给我买钻石项链,解不出来,就买辆兰博基尼吧!”,只见纸上写着:
如果一个数字只含有0和1,那么这个数字我称为漂亮数,比如1, 0, 11, 10111这些数都是漂亮数,而2,3,200,91这些都不是,现在给你一个数字n,你是否能够把它拆成几个漂亮数的和,并且这些漂亮数的个数最少?
姚师姐大为震惊,当然不是因为兰博基尼很贵,他不差钱,而是因为傻白甜的老婆居然会出题考自己,姚师姐成功在1s内解出了这道题目,现在这道题目被媒体扒了出来,你是否有能力达到Gakki老公的水平呢?

输入

第一行输入一个样例数T,表示一共有多少数字需要计算,接下来有T行,每行1个数字n,对于每个数字n,求出组成它的最少数量的漂亮数字。1<=T<=10000, 1<=n<=1e6

输出

对于每个数字n,输出两行答案,第一行是漂亮数的个数,第二行是组成它的漂亮数,按大小从小到大输出,并且在升序情况下,小的数字尽量小。

例如113 = 1 + 11 + 101 = 1 + 1 + 111

你所得到的答案应该是1+1+111。

121 = 10 + 111 = 11 + 110

你所得到的答案应该是10+111。

样例输入

2
9
32

样例输出

9
1 1 1 1 1 1 1 1 1
3
10 11 11

提示

错误代码

#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    int i,k,l,n,p,q,r,t;
    int c[1000],a[1000],an;
    cin>>t;
    a[0]=0;
    a[1]=1;
    a[2]=10;
    an=3;
    q=1;
    r=1;
    l=1;
    while(t--)
    {
    	cin>>n;
    	while(n>a[an-1])
    	{
	     	a[an]=a[an-1]+a[l]-a[l-1];
	     	l++;
	     	an++;
			if(l-1==q)
			{
				q=an-1;
				r++;
				a[an++]=pow(10,r);
				l=1;
			}
        }
        k=0;
        while(n>0)
	    {
	    	if(n%10==0)
			{
				for(i=1;i<an;i++)
			    {
			   		if(a[i]>n&&a[i]%10==0)
			     		break;
			     	else if(a[i]<=n&&a[i]%10==0)
			     		c[k]=a[i]; 
				}
				n=n-c[k];
				k++;
			} 
			else
			{
				for(i=1;i<an-1;i++)
			    {
			     	if(a[i]<=n)
			     		c[k]=a[i]; 
			   		else if(a[i]>n)
			   			break;
				}
				n=n-c[k];
				k++;	
			}
	    }
	    cout<<k<<"\n";
		for(i=k-1;i>=0;i--)
		{
			if(i!=0)
				cout<<c[i]<<" ";
			else
				cout<<c[i]<<"\n"; 
		}    
	}
         
} 

AC代码

#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    int s,a,t,i,k,l,n,c[1000];
    char ch[100];
    cin>>t;
    while(t--)
    {
    	cin>>n;
    	memset(c,0,sizeof(c));
        k=0;
        while(n>0)
	    {
	    	s=n;
	    	l=0;
	    	while(s>0)
	    	{
		    	a=s%10;
		    	if(a>0)
		    		ch[l++]='1';
		    	else if(a==0)
		    		ch[l++]='0';
		    	s/=10;
		    }
		    for(i=l-1;i>=0;i--)
		    {
		    	if(ch[i]=='1')
		    		c[k]=c[k]*10+1;
		    	else if(ch[i]=='0')
		    		c[k]=c[k]*10;
			}
	    	n=n-c[k];
	    	k++;
	    }
	    cout<<k<<"\n";
		for(i=k-1;i>=0;i--)
		{
			if(i!=0)
				cout<<c[i]<<" ";
			else
				cout<<c[i]<<"\n"; 
		}    
	}
         
} 

思考

一开始打算是用数组保存所有的漂亮数,每次减去最接近的漂亮数
首先出现问题120数据会减111+9个1→加入10的倍数判断解决
然后发现9050这种数据会用1111去减,这样在如果仍加入判断条件去分割十分困难
思考后发现,对一个数,每一个位不为0对应1,等于0则对应1
如:9050→1010
这样子就可以减去最合适的数
接着打算取余直接存进整型数组,然后发现这样子有多个0的时候不好判断,
最后改用字符数组存1和0,再化位整型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值