平方数かどうかの判定
さっさとこうすればよかったんじゃないか。
int main(){ ULL n = 0; ULL oldn; ULL i = 0; while(true){ ULL rt = ULL(sqrt(double(n))); if(rt * rt != n || rt != i){ MSG(NG); DP(i); break; } i++; oldn = n; n += i * 2 - 1; if(oldn > n) break; } MSG(END); }
2分半CPUをぶんまわして「平方数なのに平方数ではないと判定されるケース」がないことを確認した。一方rt * rt == nでチェックするので「平方数ではないのに平方数だと判定されるケース」もない(乗算でオーバーフローしたら別だけど今回はしないことがわかっている)
というわけでunsigned long longな整数が平方数かどうかの判定はdoubleにしてsqrtして結果を2乗したら元に戻るかどうかを見る方法で十分、という結論が出た。どうするのが最速かを考えるのはやめておく。今日はC++しすぎてかなり消耗した。