ABC414 C
今回の問題:https://atcoder.jp/contests/abc414/tasks/abc414_c
問題
問題の内容は$A$と$N$が与えられるから10進数とA進数で回文(左右対称)になっている$N$以下の数字の総和を出力せよというもの
制約
$1≤A≤9$
$1≤N≤10^{12}$
条件的に$O(N)$は無理だとわかるので$N$以下の数値をすべて試していたらTLEになる
方向性
問題の制約の範囲内で回文になっている10進数をすべて配列に入れてそれをすべて確かめる
ループの最大値的に10進数の回文を作るオーダーが基準になりそう
メモはこんな感じ
こんなかんじで続けると12桁時点での数もまあ収まりそう
解説によるオーダーは$O(\sqrt{N}logN)$らしい
それでできてしまったのがこれ
※マクロは省略してあります
void ntom(const string str, const int n, const int m, string &res)
{
unsigned long sum = 0;
for (char c : str)
{
sum = sum * n + (c - '0');
}
res = "";
do
{
int num = sum % m;
res = static_cast<char>(num + '0') + res;
sum /= m;
} while (sum);
}
int main()
{
ll A, N;
cin >> A >> N;
ull ans = 0;
vector<string> v;
// 1
rep(i, 1, 10)
{
v.push_back(to_string(i));
}
// 2
rep(i, 1, 10)
{
v.push_back(to_string(i * 10 + i));
}
// 3
rep(i, 1, 10)
{
rep(j, 0, 10)
{
v.push_back(to_string(i * 100 + j * 10 + i));
}
}
// 4
rep(i, 1, 10)
{
rep(j, 0, 10)
{
v.push_back(to_string(i * 1000 + j * 100 + j * 10 + i));
}
}
// 5
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
v.push_back(to_string(i * 10000 + j * 1000 + k * 100 + j * 10 + i));
}
}
}
// 6
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
v.push_back(to_string(i * 100000 + j * 10000 + k * 1000 + k * 100 + j * 10 + i));
}
}
}
// 7
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
rep(l, 0, 10)
{
v.push_back(to_string(i * 1000000 + j * 100000 + k * 10000 + l * 1000 + k * 100 + j * 10 + i));
}
}
}
}
// 8
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
rep(l, 0, 10)
{
v.push_back(to_string(i * 10000000 + j * 1000000 + k * 100000 + l * 10000 + l * 1000 + k * 100 + j * 10 + i));
}
}
}
}
// 9
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
rep(l, 0, 10)
{
rep(m, 0, 10)
{
v.push_back(to_string(i * 100000000 + j * 10000000 + k * 1000000 + l * 100000 + m * 10000 + l * 1000 + k * 100 + j * 10 + i));
}
}
}
}
}
// 10
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
rep(l, 0, 10)
{
rep(m, 0, 10)
{
v.push_back(to_string(i * 1000000000 + j * 100000000 + k * 10000000 + l * 1000000 + m * 100000 + m * 10000 + l * 1000 + k * 100 + j * 10 + i));
}
}
}
}
}
// 11
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
rep(l, 0, 10)
{
rep(m, 0, 10)
{
rep(n, 0, 10)
{
v.push_back(to_string(i * 10000000000 + j * 1000000000 + k * 100000000 + l * 10000000 + m * 1000000 + n * 100000 + m * 10000 + l * 1000 + k * 100 + j * 10 + i));
}
}
}
}
}
}
// 12
rep(i, 1, 10)
{
rep(j, 0, 10)
{
rep(k, 0, 10)
{
rep(l, 0, 10)
{
rep(m, 0, 10)
{
rep(n, 0, 10)
{
v.push_back(to_string(i * 100000000000 + j * 10000000000 + k * 1000000000 + l * 100000000 + m * 10000000 + n * 1000000 + n * 100000 + m * 10000 + l * 1000 + k * 100 + j * 10 + i));
}
}
}
}
}
}
for (string x : v)
{
if (stoull(x) > N)
break;
string k;
ntom(x, 10, A, k);
if (k == string(k.rbegin(), k.rend()))
{
ans += stoull(x);
}
}
cout << ans << el;
}
こんなコードですがACになってしまいます/(^o^)\ナンテコッタイ
10進数の数値をA進数の数値の文字列にする関数はこちらhttps://qiita.com/hanpeno/items/4fa5fbea04c2db1ae722 を使わせていただきました 感謝感謝
回文かの確認も最初はfor文で回していたのですがググっていたらstringのコピーインストラクタを使えば行けるという記事https://www.delftstack.com/ja/howto/cpp/cpp-palindrome/ を見かけたので採用
正直再帰とか使えば実装できる気がするが考えるより12回コピペしたほうが早いと思ったのでこんな結果に
競技プログラミングだからいいけど共同作業とかする時はもっと見やすいコードを書けという自分への戒め