SRM 466 250pt: LotteryCheating
問題概要
L(<=10)桁の数字が与えられる。最小何桁の数字を動かせば、約数の個数が奇数になるか求める問題。
考えたこと
- (当時は全く手が出なかった問題)
- 約数の個数が奇数=平方数。
- なので候補の上限10^Lのうち調べるのは10^(L/2)だけでよい。
- 後は変換するだけ。0でパディングするのが面倒なので両方桁数13に増やそう。
- サンプル通った。投げる。WA。
- 勝手に桁数増やしちゃダメじゃん。文字列に変換したとき、桁数がもとのを越えたら即アウトの判定をすれば良い。
- 修正後無事通った。
practiceで通ったコード
計算量O(10^(L/2)*L)。
#include <string> #include <sstream> using namespace std; typedef long long int64; const int INF = 1<<29; const int MAX_LEN = 15; const int64 MAX_N = (int64)1000*1000*1000*10; struct LotteryCheating { int minimalChange(string ID) { //当たり=平方数を全探索 int ret = INF; for(int64 x=0; x*x <= MAX_N; x++){ ret = min(ret, get_distance(ID, to_str(x*x) ) ); } return ret; } int get_distance(const string& a, string b){ if(a.length() < b.length()){ return INF; } if(a.length() > b.length()){ b = string(a.length() - b.length(), '0') + b; } int ret = 0; for(int i=0; i<(int)a.length(); i++){ if(a[i] != b[i]){ ret++; } } return ret; } string to_str(int64 x){ stringstream ss; ss << x; return ss.str(); } };