Problem
- 给定一个位数为2n的数字,定义该数字的幸运度为将后n位放至前n位在七段码下重叠的段的个数。要求找一个最小的比给定数字大且幸运度更大的数字且位数为2n。
Solution
- 贪心。只改变前i位的情况下能找到答案就不要修改i+1~2n位。
- 设需要修改的最高位为pos,分两种情况处理:pos>n和pos<=n。
- 在寻找最大位的过程中,每移动一位要保证前面位产生的贡献达到最大,此时不需要考虑前i-1位数的大小,因为前i-1位解决不了,第i位需从更大的数开始枚举。
- 具体步骤:找最大位,从最大位到最小位依次贪心,使当前位在满足题意的基础上尽可能小。细节处理见代码和代码注释。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dig[200005],cnt,dig0[200005],hl,ans[15][15],wa,ac,ac0,pos,mx[200005];
string k;
void init()
{
ans[0][0]=6;
ans[0][1]=ans[1][0]=2;
ans[0][2]=ans[2][0]=4;
ans[0][3]=ans[3][0]=4;
ans[0][4]=ans[4][0]=3;
ans[0][5]=ans[5][0]=4;
ans[0][6]=ans[6][0]=5;
ans[0][7]=ans[7][0]=3;
ans[0][8]=ans[8][0]=6;
ans[0][9]=ans[9][0]=5;
ans[1][1]=2;
ans[1][2]=ans[2][1]=1;
ans[1][3]=ans[3][1]=2;
ans[1][4]=ans[4][1]=2;
ans[1][5]=ans[5][1]=1;
ans[1][6]=ans[6][1]=1;
ans[1][7]=ans[7][1]=2;
ans[1][8]=ans[8][1]=2;
ans[1][9]=ans[9][1]=2;
ans[2][2]=5;
ans[2][3]=ans[3][2]=4;
ans[2][4]=ans[4][2]=2;
ans[2][5]=ans[5][2]=3;
ans[2][6]=ans[6][2]=4;
ans[2][7]=ans[7][2]=2;
ans[2][8]=ans[8][2]=5;
ans[2][9]=ans[9][2]=4;
ans[3][3]=5;
ans[3][4]=ans[4][3]=3;
ans[3][5]=ans[5][3]=4;
ans[3][6]=ans[6][3]=4;
ans[3][7]=ans[7][3]=3;
ans[3][8]=ans[8][3]=5;
ans[3][9]=ans[9][3]=5;
ans[4][4]=4;
ans[4][5]=ans[5][4]=3;
ans[4][6]=ans[6][4]=3;
ans[4][7]=ans[7][4]=2;
ans[4][8]=ans[8][4]=4;
ans[4][9]=ans[9][4]=4;
ans[5][5]=5;
ans[5][6]=ans[6][5]=5;
ans[5][7]=ans[7][5]=2;
ans[5][8]=ans[8][5]=5;
ans[5][9]=ans[9][5]=5;
ans[6][6]=6;
ans[6][7]=ans[7][6]=2;
ans[6][8]=ans[8][6]=6;
ans[6][9]=ans[9][6]=5;
ans[7][7]=3;
ans[7][8]=ans[8][7]=3;
ans[7][9]=ans[9][7]=3;
ans[8][8]=7;
ans[8][9]=ans[9][8]=6;
ans[9][9]=6;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
init();
cin>>k;
for(int i=0; i<k.size(); i++)
{
dig0[k.size()-i]=k[i]-'0';
dig[k.size()-i]=dig0[k.size()-i];
}
cnt=k.size();
hl=cnt/2;
for(int i=1; i<=hl; i++)
{
wa+=ans[dig0[i]][dig0[i+hl]];
ac+=ans[dig[i]][dig[i+hl]];
}
ac0=ac;
for(int i=1; i<=hl; i++)
{
bool cmp=0;
if(i>1)
{
ac0-=mx[i-1];
ac0+=ans[dig[i-1+hl]][dig[i-1+hl]];
for(int j=9; j>=0; j--)
if(ans[dig[i-1+hl]][dig[i-1+hl]]==ans[dig[i-1+hl]][j])
{
cmp=j>dig[i-1];
break;
}
mx[i-1]=ans[dig[i-1+hl]][dig[i-1+hl]];
}
for(int j=cmp?dig[i]:dig[i]+1; j<=9; j++)
mx[i]=max(mx[i],ans[dig[i+hl]][j]);
ac0=ac0-ans[dig[i+hl]][dig[i]]+mx[i];
if(ac0>wa)
{
pos=i;
break;
}
}
if(!pos)
{
ac0=ac;
for(int i=cnt; i>hl; i--)
{
ac0=ac0-ans[dig[i]][dig[i-hl]]+ans[dig[i]][dig[i]];
dig[i-hl]=dig[i];
}
for(int i=hl+1; i<=cnt; i++)
{
bool cmp=0;
if(i>hl+1)
{
ac0=ac0-mx[i-1]+7;
cmp=dig[i-1]<8;
mx[i-1]=7;
}
for(int j=cmp?dig[i]:dig[i]+1; j<=9; j++)
mx[i]=max(mx[i],ans[j][j]);
ac0=ac0-ans[dig[i]][dig[i-hl]]+mx[i];
if(ac0>wa)
{
pos=i;
break;
}
}
if(!pos)
{
cout<<-1;
return 0;
}
bool cmp=0;
for(int i=pos; i>hl; i--)
{
ac0-=mx[i];
for(int j=(cmp?0:dig[i]); j<=9; j++)
{
if(i==pos&&j==dig[i]) j=dig[i]+1;
if(ac0+ans[j][j]>wa)
{
ac0+=ans[j][j];
if(j>dig[i]) cmp=1;
dig[i]=j;
dig[i-hl]=j;
break;
}
}
}
for(int i=cnt; i>hl; i--)
{
ac0=ac0-ans[dig[i]][dig[i-hl]]+ans[dig[i]][dig[i]];
dig[i-hl]=dig[i];
}
for(int i=hl; i>=1; i--)
{
ac0-=ans[dig[i+hl]][dig[i]];
for(int j=0; j<=9; j++)
{
if(ac0+ans[dig[i+hl]][j]>wa)
{
ac0+=ans[dig[i+hl]][j];
dig[i]=j;
break;
}
}
}
for(int i=cnt; i>0; i--)
cout<<dig[i];
}
else
{
bool cmp=0;
for(int i=pos; i>=1; i--)
{
ac0-=mx[i];
for(int j=(cmp?0:dig[i]+1); j<=9; j++)
{
if(ac0+ans[dig[i+hl]][j]>wa)
{
if(j>dig[i]) cmp=1;
dig[i]=j;
ac0+=ans[dig[i+hl]][j];
break;
}
}
}
for(int i=cnt; i>0; i--)
cout<<dig[i];
}
return 0;
}