http://arc075.contest.atcoder.jp/tasks/arc075_d
解説(複雑で適当なので微妙な解説)
http://arc075.contest.atcoder.jp/submissions/1328295
メモ化再帰で解いていく。
あらかじめ、Dは頭に0を追加して24桁にしておく。
以下のような関数を定義する。
f(L, R, Lu, Ru) [L,R]桁目がまだ未確定で、繰り上がり分としてLuが必要で、R桁目未満からの繰り上がりがRuであるときに有効な組合せ
これを使うと、答えはf(0,23,0,0)+f(1,23,0,0)+...+f(x,23,0,0)である。
(xは初めて0以外が出てくる最も左の桁目)
関数の中身はR==23かどうかで分岐しているが、これは、R==23なら先頭は0ではダメ、R!=23なら先頭は0でも良いというLeading-Zero対策の分岐である。
その中で基本的には、L桁目とR桁目に置く数字を全列挙していく。
L桁目に置く数字は反転してR桁目に来るので、条件が合うようなものだけ、利用していく。
string D; //--------------------------------------------------------------------------------------------------- int memo[24][24][2][2]; int f(int L, int R, int Lu, int Ru) { int &res = memo[L][R][Lu][Ru]; if (0 <= res) return res; res = 0; if (R == 23) { if (L == R) res = 0; else if(L + 1 == R) { rep(a, 1, 10) rep(b, 0, 10) { int t = b + D[R] - '0' + Ru; int tt = t / 10; if (t % 10 != a) continue; int s = a + D[L] - '0' + tt; if (s % 10 != b) continue; if (s / 10 != Lu) continue; res++; //printf("(%d %d)\n", a, b); } } else { rep(a, 1, 10) rep(b, 0, 10) { if ((b + D[R] - '0' + Ru) % 10 != a) continue; int Ruu = (b + D[R] - '0' + Ru) / 10; if ((a + D[L] - '0') / 10 == Lu && (a + D[L] - '0') % 10 == b) res += f(L + 1, R - 1, 0, Ruu); if ((a + D[L] - '0' + 1) / 10 == Lu && (a + D[L] - '0' + 1) % 10 == b) res += f(L + 1, R - 1, 1, Ruu); } } } else { if (L == R) { rep(a, 0, 10) { if ((a + D[L] - '0' + Ru) / 10 != Lu) continue; if ((a + D[L] - '0' + Ru) % 10 != a) continue; res++; //printf("[%d]\n", a); } } else if (L + 1 == R) { rep(a, 0, 10) rep(b, 0, 10) { int t = b + D[R] - '0' + Ru; int tt = t / 10; if (t % 10 != a) continue; int s = a + D[L] - '0' + tt; if (s % 10 != b) continue; if (s / 10 != Lu) continue; res++; //printf("<%d %d>\n", a, b); } } else { rep(a, 0, 10) rep(b, 0, 10) { if ((b + D[R] - '0' + Ru) % 10 != a) continue; int Ruu = (b + D[R] - '0' + Ru) / 10; if ((a + D[L] - '0') / 10 == Lu && (a + D[L] - '0') % 10 == b) res += f(L + 1, R - 1, 0, Ruu); if ((a + D[L] - '0' + 1) / 10 == Lu && (a + D[L] - '0' + 1) % 10 == b) res += f(L + 1, R - 1, 1, Ruu); } } } return res; } //--------------------------------------------------------------------------------------------------- void _main() { cin >> D; while (D.size() < 24) D = "0" + D; rep(L, 0, 24) rep(R, 0, 24) rep(Lu, 0, 2) rep(Ru, 0, 2) memo[L][R][Lu][Ru] = -1; //cout << D << endl; int L = 0; while (D[L] == '0') L++; int ans = 0; rep(x, 0, L + 1) { //printf("{{ %d }}\n", x); ans += f(x, 23, 0, 0); } cout << ans << endl; }