公式

C - Security 2 解説 by sheyasutaka


以下では \(S\) の長さを \(N\) とおきます。

\(t\) の文字数は、ボタン A を押すと \(1\) 増えて、ボタン B を押すと変化しません。 なので、ボタン A を押す回数は \(N\) 回とわかります。

以下の行動の前後では \(t\) は変化しないので、以下の行動は行わないとしても操作回数の最小値は悪化しません。

  • ボタン A を最初に押すよりも前に、ボタン B を押す。
  • ボタン B を \(10\) 回連続で押す。

\(1 \leq i \leq N\) について、\(i\) 回目にボタン A を押してから次にボタン A を押すまでのあいだに何回ボタン B を押すかを \(b_i\) とおくと、上の議論から \(0 \leq b_i \leq 9\) としてよいです。

このとき、\(t\)\(j\) 文字目が \(S_j\) になるのは、\((b_j + \dots + b_N) \bmod 10 = S_j\) になるときです。

\(j=N\) のときは \(b_N = S_j\) となるので、\(j<N\) のときについて考えます。 \(j+1\) 文字目について同様の式を立てると \((b_{j+1} + \dots + b_N) \bmod 10 = S_{j+1}\) となり、さきほどの式からこの式を引くことで \(b_j \equiv S_{j} - S_{j+1}\ \pmod{10}\) が分かります。 これを満たす \(b_i\) であって \(0 \leq b_i \leq 9\) の範囲にあるものは、\((10 + S_{j} - S_{j+1}) \bmod 10\) で求まります。

したがって、上で求めた \(b_j\) の値を \(1 \leq j \leq N\) について足し合わせ、さらに \(N\) を加えた値が答えとなります。

C++ での実装例を以下に示します。

#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::string;


int main(void){
	string s;
	cin >> s;

	int sum = 0;
	int n = s.size();
	for (int i = n-1; i >= 0; i--) {
		int v = s[i] - '0';
		int u = ((i < n-1) ? (s[i+1] - '0') : 0);
		int b = (10 + v - u) % 10;
		sum += b;
	}

	int ans = sum + n;
	cout << ans << "\n";

	return 0;
}

投稿日時:
最終更新: