ちょっと手間取った。
https://yukicoder.me/problems/no/3245
問題
8ドル,88ドル,888ドル,8888ドルの紙幣がそれぞれ大量にあるとき、合計Nドルをお釣りなく払い切ることができるか。
ただし、1種類の紙幣が半分以上を占めてはならない。
できるなら一例を示せ。
解法
あらかじめ全体を8で割っておき、1,11,111,1111ドルでNドルを払えるかを考える。
Nが12の倍数の時、1ドルと11ドルを半々ずつ使うことができる。
ただし、問題の条件より111ドル・1111ドルも多少は使わないといけない。
そこで以下のようにした。
- Nが10000以下の場合は総当たり。
- そうでない場合、111ドル・1111ドルの紙幣を少数使うことを総当たりし、残りが12の倍数になったら、1ドルと11ドル紙幣を半々で使う。
int T; ll N; vector<int> V[10101]; void solve() { int i,j,k,l,r,x,y; string s; for(int d=0;d*1111<10000;d++) { for(int c=0;d*1111+c*111<10000;c++) { for(int b=0;d*1111+c*111+b*11<10000;b++) { for(int a=0;d*1111+c*111+b*11+a<10000;a++) { int s=a+b+c+d; int v=d*1111+c*111+b*11+a; if(2*a>=s) continue; if(2*b>=s) continue; if(2*c>=s) continue; if(2*d>=s) continue; V[v]={a,b,c,d}; } } } } cin>>T; while(T--) { cin>>N; if(N%8) { cout<<-1<<endl; continue; } N/=8; if(N>=10000) { FOR(i,13) FOR(j,3) { if(i&&(N-i*111-j*1111)%12==0) { ll a=(N-i*111-j*1111)/12; cout<<a<<" "<<a<<" "<<i<<" "<<j<<endl; assert(i*2<a+a+i); assert(a*12+i*111+j*1111==N); i=j=100; break; } } } else { if(V[N].empty()) { cout<<-1<<endl; } else { ll a=V[N][0]+V[N][1]+V[N][2]+V[N][3]; ll s=V[N][0]+V[N][1]*11+V[N][2]*111+V[N][3]*1111; assert(s==N); assert(V[N][0]*2<a); assert(V[N][1]*2<a); assert(V[N][2]*2<a); assert(V[N][3]*2<a); cout<<V[N][0]<<" "<<V[N][1]<<" "<<V[N][2]<<" "<<V[N][3]<<endl; } } } }
まとめ
細かいコーナーケースで手間取ってしまった。