题目大意
测试点包含T组数据,对于每组数据,输入一个小棒的数量n,用这n根小棒拼出一个不含前导零的正整数x,输出能拼出x的最小值,每个数字的拼法如下:
解题思路
我们先给自己的思维做一下预处理,观察每个数字所需小棒的数量,列出一个数组:
sticks[10]={6,2,5,5,4,5,6,3,7,6};
不难发现,8的所用小棒最多;数字3,5,6,9这几个数字是没用的,拿3来举例,3与2这两个数字所用小棒都是5根,所以要拿5根小棒的数时,必定选择更小的2才会更优,而不是3,所以3真的真的没什么用。
还有一个可以偷鸡教你摆烂的小技巧,我们发现此题只有一个数据点,所以CCF肯定有什么规律怕被你发现,基本上可以断定这是道找规律题。
那如何找到规律呢?
方法1:电脑能干的事为什么要人做呢?
我们可以写一个程序来找规律。
#include<bits/stdc++.h>
using namespace std;
long long read(){
long long dat=0,t=1;
char ch;
ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')t=-t;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
dat=(dat<<1)+(dat<<3)+(ch&15);
ch=getchar();
}
return dat*t;
}
long long i,n,k,b[10];
long long ans;
long long a[10]={6,2,5,5,4,5,6,3,7,6};
void dfs(long long k,long long c[]){
if(k<0)return;
if(k==1){
return;
}
if(k==0){
long long num=0;
long long flag=-1;
for(long long j=1;j<=9;j++){//为了防止数字有前导0
if(c[j]>0){
flag=j;
num=j;
break;
}
}
if(num==0)return;
for(long long j=0;j<=9;j++){
long long p=c[j];
if(flag==j)p=p-1;//有一个数字被用在了开头,故要减去
for(long long q=1;q<=p;q++){
num=num*10+j;
}
}
if(num<ans){
ans=num;
}
return;
}
for(long long j=0;j<=9;j++){
if(k>=a[j]){
c[j]=c[j]+1;
dfs(k-a[j],c);
c[j]=c[j]-1;
}
}
return;
}
int main(){
for(i=1;i<=30;i++){
if(i==1){
cout<<-1<<endl;//所有数字所需的小棒数量都大于等于2, 1根小棒时组成不了任何数字
continue;
}
ans=99999999;
dfs(i,b);
if(i==6)cout<<6<<endl;//0和6都只需要6根小棒,但0不是正整数
else cout<<ans<<endl;
}
return 0;
}
运行一下,不难发现结果为:
-1
1
7
4
2
6
8
10
18
22
20
28
68
88
108
188
200
208
288
688
888
1088
1888
2008
2088
2888
6888
8888
10888
18888
规律显而易见:1~14根小棒可以打表,而从15根开始,每7个为一组有规律,之后无脑加8。
方法2:动用聪明的大脑
我们平常在比较2个数大小时是如何比较的呢?
先比较位数,再从首位开始往后逐位比较 。
所以说,我们想要一个数较小,肯定得先使它位数最少。
而小棒总数是一定的,所以我们要多用消耗小棒数多的数字,才能使位数尽量少。
也就是说,我们需要多用数字8。
所以当小棒总数多的时候,多用8可以与其他数字拉开好几位数的差距;但当小棒数量少时,其他数字组成的数可能与多个数字8组成的数拉不开差距,如0,6,9三个数字用的小棒数为6根,仅次于数字8的7根,也就是说,在每一位上,选0,6,9都只比8少一根小棒,而最少的1需要2根小棒,也就是说,至少需要能摆成2/1=2位数的小棒才能使数字8拉开差距,也就是至少2*7=14根小棒之后才有规律,所以1~14根小棒的答案得手算,从15根小棒开始就可以找规律了。
正解
找规律代码,当n小于等于14时打表,当n大于14时,若n%7==1,2,3,4,5,6,0 则对应为108,188,200,208,288,688,888,之后再加上(n+6)/7-2个8即可。
code
#include<bits/stdc++.h>
using namespace std;
long long read(){
long long dat=0,t=1;
char ch;
ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')t=-t;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
dat=(dat<<1)+(dat<<3)+(ch&15);
ch=getchar();
}
return dat*t;
}
long long t,n,m,i,a[8]={4444,-1,1,7,4,2,6,8};
int main(){
t=read();
for(;t>=1;t--){
n=read();
m=(n+6)/7-2;
if(n<=7){
printf("%lld\n",a[n]);
continue;
}
if(n%7==1){
printf("10");
}
if(n%7==2){
printf("18");
}
if(n%7==3){
printf("20");
}
if(n%7==4){
printf("20");
}
if(n%7==5){
printf("28");
}
if(n%7==6){
printf("68");
}
if(n%7==0){
printf("88");
}
for(i=1;i<=m;i++){
printf("8");
}
printf("\n");
}
return 0;
}
2850

被折叠的 条评论
为什么被折叠?



