1と四則演算だけで2011を作れ
virottoさんのとある情報工学科の大学生活 CTF:2011年問題の考察に触発されて…
問題概要
(省略)
解法
問題文より1の個数は最大16個.
四則演算では*と/が優先されるので,*と/のみで作れるものをリストアップする.
最後にそれと+と-を使って作れるものをリストアップする.
その他
最初はvirottoさんと同じような解法で解こうと思ったけどC++でパーサーを実装するのが面倒だったのでこの解法に.
IdeOneで実験した結果0.19sなので割と高速.
JavaScriptでevalという発想は無かった!
本番では解けなかった(ように見えた)けど,5日目に問い合わせてみたら,ジャッジのミスということが分かり実際は解けていたので一安心.
実装(C++)
本番の実装とは違います.
#include <iostream> #include <tr1/unordered_map> using namespace std; using namespace tr1; #define REP(i,x) for(int i=0;i<(int)(x);i++) #define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++) int value[9]={1,11,111,1111,11111,111111,1111111,11111111,111111111}; string value_str[9]={"1","11","111","1111","11111","111111","1111111","11111111","111111111"}; const int CORRECT=2011; unordered_map<int,string> v1[17];//*と/のみで生成可能な数値 unordered_map<int,string> v2[17];//+と-も用いて生成可能な数値 #define SOLVE1(p,k,q){\ string next_str=p->second+ #k +value_str[q];\ long long next=(long long)p->first k value[q];\ if(next<=1e9&&(v1[i+j+1][next]==""||v1[i+j+1][next]>next_str))v1[i+j+1][next]=next_str;\ } #define SOLVE2(p,k,q){\ string next_str=p->second+ #k +q->second;\ int next=p->first k q->first;\ if(v2[i+j][next]==""||v2[i+j][next]>next_str)v2[i+j][next]=next_str;\ } int main() { REP(i,9)if(i)v1[i+1][value[i]]=value_str[i]; REP(i,16)REP(j,9){ if(i+j+1>=17)continue; if(j)FOR(k,v1[i]){ SOLVE1(k,*,j); SOLVE1(k,/,j); } } v1[1][value[0]]=value_str[0]; v2[0][0]=""; REP(i,16)REP(j,17)FOR(k,v1[j]){ if(i+j>=17)continue; FOR(l,v2[i]){ SOLVE2(l,+,k); SOLVE2(l,-,k); } } REP(i,17){ if(v2[i][CORRECT]!=""){ cout<<i<<":"<<v2[i][CORRECT].substr(1)<<endl; break; } } return 0; }