結果
| 問題 | No.315 世界のなんとか3.5 |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-10-05 10:15:03 |
| 言語 | D (dmd 2.113.0) |
| 結果 |
AC
不安定
|
| 実行時間 | 1,091 ms / 2,000 ms |
| + 760µs | |
| コード長 | 2,415 bytes |
| 記録 | |
| コンパイル時間 | 2,926 ms |
| コンパイル使用メモリ | 203,120 KB |
| 実行使用メモリ | 73,112 KB |
| 最終ジャッジ日時 | 2026-10-05 10:15:22 |
| 合計ジャッジ時間 | 16,693 ms |
|
ジャッジサーバーID (参考情報) |
judge3_0 / judge1_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 36 |
ソースコード
module main;
// https://kmjp.hatenablog.jp/entry/2015/12/09/0900 より
// claude ai より
// 数え上げ、剰余
import std;
immutable MOD = 10L ^^ 9 + 7;
long[] p10;
long[][][] memo;
// 多次元配列をある値で埋める
void fill(A, T)(ref A a, T value) if (isArray!A)
{
alias E = ElementType!A;
static if (isArray!E) {
foreach (ref e; a)
fill(e, value);
} else {
a[] = value;
}
}
long dfs(char[] S, int d, int m, int lead)
{
int len = S.length.to!int;
if (d >= len) return m == 0;
if (memo[d][m][lead] >= 0) return memo[d][m][lead];
long ret = 0;
if (lead == 1) {
foreach (i; 0 .. S[d] - '0') {
if (i == 3) ret += p10[len - 1 - d];
else ret += dfs(S, d + 1, (m + i) % 3, 0);
}
if (S[d] == '3') {
long pat = 0;
foreach (i; d + 1 .. len) pat = (pat * 10 + (S[i] - '0')) % MOD;
ret += pat + 1;
} else {
ret += dfs(S, d + 1, (m + S[d] - '0') % 3, 1);
}
} else {
foreach (i; 0 .. 10) {
if (i == 3) ret += p10[len - 1 - d];
else ret += dfs(S, d + 1, (m + i) % 3, 0);
}
}
return memo[d][m][lead] = ret % MOD;
}
// 文字列で表された数を1減らす
void dec(ref char[] A)
{
A.reverse;
foreach (ref r; A) {
if (r != '0') {
r--;
break;
}
r = '9';
}
if (A.length > 1 && A.back == '0') A.length -= 1;
A.reverse;
}
int greed(int v, int p)
{
int ret = 0;
foreach (i; 1 .. v + 1) {
if (i % p == 0) continue;
int j = i;
while (j) {
if (j % 10 == 3) break;
j /= 10;
}
if (j || (i % 3 == 0)) ret++;
}
return ret;
}
long calc(char[] S, long P)
{
auto dp = new long[][](2, 3), t = new long[](2);
if (S.length <= 5) return greed(S.to!int, P.to!int);
long ret = 0;
int low = S[$ - 5 .. $].to!int;
S = S[0 .. $ - 5];
foreach (j; 0 .. 2) {
fill(memo, -1);
foreach (i; 0 .. 3) dp[j][i] = dfs(S, 0, i, 1);
foreach (r; S) t[j] = (t[j] * 10 + r - '0') % MOD;
t[j]++;
dec(S);
}
foreach (i; 0 .. 100_000) {
int v = i;
if (i % P == 0) continue;
while (v) {
if (v % 10 == 3) break;
v /= 10;
}
if (v) ret += t[i > low];
else ret += dp[i > low][i % 3];
}
return ret % MOD;
}
void main()
{
// 入力
char[] A, B;
long P;
readln.chomp.formattedRead("%s %s %d", A, B, P);
// 答えの計算
p10 = 1L.recurrence!((a,n) => a[n-1] * 10 % MOD).take(B.length + 1).array;
memo = new long[][][](B.length + 1, 3, 2);
dec(A);
// 答えの出力
writeln((calc(B, P) + MOD - calc(A, P)) % MOD);
}