题目描述
我们把十进制下每一位都是偶数的数字叫做“二数”。
小埃表示自己很聪明,最近他不仅能够从小数到大:2,3,4,5....,也学会了从大数到小:100,99,98...,他想知道从一个数开始数最少的数就得到一个二数。但是聪明的小森已经偷偷在心里算好了小埃会数到哪个二数,请你求出他要数到哪个数吧。
换句话说,给定一个十进制下最多105位的数字,请你求出和这个数字的差的绝对值最小的二数,若答案不唯一,输出最小的那个。
也就是说,给定数字n,求出m,使得abs(n-m)最小且m[i] mod 2 = 0
题解:
算一个构造题
比赛时想到了,但是看错数据范围,发现自己写的不对。。。
n<10^,正常肯定不好做,当然可以写大数加减?但是感觉不是正解
正解是按照题目要求构造
因为数很大用string读取
我们要找离目标数最近的二数,就像从目标数的最高位开始,当遇到不是偶数时,假设该位为x,x时奇数,那么离x最近的二数又两种情况(x+1)000...或者(x-1)888....
为什么是这样?因为x是奇数,要让x变为偶数要么加1,要么减一,如果+1,要让二数距离原数最近,后面就要跟最小的二数,最小的二数就是0,所以时(x+1)0000
-1的情况类似,后面是跟最大的二数
那(x+1)000...和(x-1)888..哪个离目标最近?我将两者相加求平均数可得,x444..正好是他们的中间值,当目标数小于x444时,说明里(x-1)888更近,相反离(x+1)000更近
注:如果x为9的话只能减1,加的话就要进位,会使前一个位的偶数+1变成奇数
代码有详细注释
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+9; char s[maxn]; int main() { //ios::sync_with_stdio(false); int t; cin>>t; while(t--) { string sum; scanf("%s",s+1); int len=strlen(s+1); int f=0;//记录是否出现偶数情况 for(int i=1;i<=len;i++) { if(!f) { int w=s[i]-'0'; if(w%2==0) { sum+=s[i]; continue; } if(w==9)//特判情况 { f=1;//已出现奇数 sum+='8'; continue; } bool f2=1;//默认的是离(x-1)888更近 for(int j=i+1;j<=len;j++) { if(s[j]=='4')continue; if(s[j]<'4')break; if(s[j]>'4') { f2=0; break; } } if(f2) { sum+=(s[i]-1); f=1; } else { sum+=(s[i]+1); f=2; } } else { if(f==1)sum+='8';//后面根888 else sum+='0';//后面根000 } } if(sum[0]=='0'&&sum.size()>1) { sum.erase(sum.begin());//避免首位是0 } cout << sum << endl; } }