SRM546 Div1 Medium(500), Div2 Hard(1000) FavouriteDigits
MがNより大きいとき、ある桁pについて、pより上位の桁ではNとMが等しく、p桁ではMの数字がNの数字より大きく、pより下位の桁は何でも良い。pより下位の桁は、digit1(d1)<digit2(d2)ならば、0 0 … 0 d1 d1 … d1 d2 d2 … d2と並べるのが最も小さくなる。pとp桁目の数を変えて、最小のものを返せば良い。
#include <algorithm> #include <vector> using namespace std; class FavouriteDigits{public: long long findNext( long long N, int digit1, int count1, int digit2, int count2 ) { const int M = 16; if ( digit1>digit2 ) swap(digit1,digit2), swap(count1,count2); vector<int> n(M); long long t = N; for ( int i=0; t>0; i++, t/=10 ) n[i] = t%10; // Nが条件を満たすかチェック int c1 = count1; int c2 = count2; int i; for ( i=M-1; n[i]==0; i-- ) ; for ( ; i>=0; i-- ) { if ( n[i]==digit1 ) c1--; if ( n[i]==digit2 ) c2--; } if ( c1<=0 && c2<=0 ) return N; // Nより大きく条件を満たす数を探す long long ans = 1LL<<62; for ( int p=0; p<M; p++ ) for ( int d=n[p]+1; d<=9; d++ ) { vector<int> t(M); for ( int i=M-1; i>p; i-- ) t[i] = n[i]; t[p] = d; int c1 = count1; int c2 = count2; int i; for ( i=M-1; t[i]==0; i-- ) ; for ( ; i>=p; i-- ) { if ( t[i]==digit1 ) c1--; if ( t[i]==digit2 ) c2--; } c1 = max(c1,0); c2 = max(c2,0); if ( c1+c2<=i+1 ) { for ( int i=0; i<c2; i++ ) t[i] = digit2; for ( int i=c2; i<c1+c2; i++ ) t[i] = digit1; long long a = 0; long long s = 1; for ( int i=0; i<M; i++ ) a += t[i]*s, s *= 10; ans = min( ans, a ); } } return ans; }};