题意:给你一个很大的数,问你小于该数的最大的优美数是多少(优美数:每一位上出现的数字都出现偶数次)
题解:直接从最后一位开始让该位减一(直到该位减到0),判断前边与后边加上该位是否符合题意,若不符合,接着往前找即可,倒着暴力的好处是遇到第一个符合条件的数一定就是答案,当然别忘了特判最高位是1,其余位是0的情况,这种情况下直接输出len-2个9即可。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char s[200005],s1[200005];
int flag[15],mark;
int main(void)
{
int t,len;
scanf("%d",&t);
while(t--)
{
mark=0;
scanf("%s",s+1);
len=strlen(s+1);
memset(flag,0,sizeof(flag));
if(len%2)
{
for(int i=1;i<=len-1;i++)
printf("9");
printf("\n");
continue;
}
for(int i=1;i<=len;i++)
flag[s[i]-'0']++;
for(int i=len;i>0;i--)
{
char c=s[i]-'0';
if(i==1 && s[i]=='1')
{
mark=2;
break;
}
flag[c]--;
for(int j=1;j<10;j++)
{
if(c<j) break;flag[c-j]++;
int num=len-i,sum=0;
for(int k=0;k<10;k++)
if(flag[k]%2)
sum++;
if(sum<=num)
{
mark=1;
s[i]=c-j+'0';
for(int k=i+1;k<=len-sum;k++)
s[k]='9';
for(int k=len-sum+1;k<=len;k++)
for(int h=9;h>=0;h--)
if(flag[h]%2)
{
s[k]=h+'0';
flag[h]=0;
break;
}
}
if(mark) break;
else
flag[c-j]--;
}
if(mark) break;
}
if(mark==2)
{
for(int i=1;i<=len-2;i++)
printf("9");
if(len%2) printf("9");
printf("\n");
}
else
printf("%s\n",s+1);
}
return 0;
}