Codeforces 95 B. Lucky Numbers
問題
super lucky numberとは、各桁が4または7であり、
4の現れる回数と7の現れる回数の等しいような数を言う。
与えられた数n以上の、最小のsuper lucky numberを求めよ。
制約条件
n≦10^5
方針
なんかBなのに難しい気が……自分がこういう問題苦手なだけなのだろうか。
頭から数字を見ていき、4,7でない数字が最初に現れたら、そこが数字を替える候補である。
そこの数字を変えてダメな場合は、一桁ずつ左へ戻りながら、
そこの数字を変えてsuper lucky numberが作れるかを見る。
super lucky numberが作れるかは、
今までに出現した4の数および、7の数、現在の位置から、
残りの4の数と7の数についての方程式が立てられ、それが0以上残りの桁数以下の整数解を持つか見てやることで判定できる。
ソースコード
なんか冗長。
string in; int n; void run(){ cin>>in; n=in.size(); in=(n%2?"0":"00")+in; int p=n%2?1:2, four=0,seven=0; n=in.size(); for(;p<n;p++){ if(in[p]=='4')four++; else if(in[p]=='7')seven++; else break; } for(;p>=0;p--){ if(in[p]=='4')four--; else if(in[p]=='7')seven--; int rest=n-p, tmp=seven-four+rest; if(tmp%2!=0)goto FAIL; tmp/=2; if(tmp<0||tmp>rest)goto FAIL; if(in[p]>='7'||in[p]>='4'&&abs(seven+1-four)>rest-1)goto FAIL; break; FAIL:; } if(in[p]>='4')in[p++]='7', seven++; for(;p<n;p++){ int rest=n-p-1,tmp=seven-four+rest-1; if(0<=tmp&&tmp<=2*rest)in[p]='4', four++; else in[p]='7', seven++; } p=0; while(in[p]=='0')p++; cout<<in.substr(p)<<endl; }