Language: C++

#include <array>
#include <cstddef>
#include <functional>
#include <iterator>
#include <numeric>
#include <vector>

template <class T, std::size_t Dimension> class multi_dimensional_vector {
public:
	static_assert(static_cast<std::size_t>(0) < Dimension,
		"Dimension must be larger than 0");

	using value_type = T;
	using size_type = std::size_t;

	using value_itr = typename std::vector<value_type>::iterator;
	using size_itr = typename std::array<size_type, Dimension>::const_iterator;
	using itr_diff = typename std::iterator_traits<value_itr>::difference_type;

	template <std::size_t D> class mdv_inner {
	public:
		value_itr front_iterator;
		size_itr size_iterator;

		mdv_inner(const value_itr f, const size_itr s)
			: front_iterator(f), size_iterator(std::next(s)) {}

		auto operator[](const size_type index) {
			return mdv_inner<D - static_cast<std::size_t>(1)>(
				front_iterator + static_cast<itr_diff>(*size_iterator * index),
				size_iterator);
		}
	};
	template <> class mdv_inner<static_cast<std::size_t>(1)> {
	public:
		value_itr front_iterator;

		mdv_inner(const value_itr f, const size_itr) : front_iterator(f) {}

		value_type &operator[](const size_type index) {
			return *(front_iterator + static_cast<itr_diff>(index));
		}
	};

	std::vector<value_type> table;
	std::array<size_type, Dimension> value_size;

	multi_dimensional_vector(const std::array<size_type, Dimension> &a,
		const value_type &x)
		: value_size(), table() {
		std::partial_sum(a.crbegin(), a.crend(), value_size.rbegin(),
			std::multiplies<size_type>());
		table.assign(value_size.front(), x);
	}

	auto operator[](const size_type index) {
		return mdv_inner<Dimension>(table.begin(), value_size.cbegin())[index];
	}
};

#include<algorithm>
#include<cstddef>
#include<iostream>
#include<string>

int main() {
	using usize = std::size_t;
	using u32 = unsigned int;

	static constexpr u32 MOD = 1000000007;


	std::string k;
	usize d;
	std::cin >> k >> d;
	std::reverse(k.begin(), k.end());
	usize n = k.size();

	multi_dimensional_vector<u32, 3> dp({ n + 1,d,2 }, 0);
	// i 文字目 | d の剰余が j | k 未満
	dp[n][0][0] = 1;

	const auto add=[](u32 &l, const u32 &r) {
		l = (l + r) % MOD;
	};

	for (usize i = n;i--;) {
		const usize c = k[i] - '0';
		for (usize j = 0;j != d;++j) {
			for (usize l = 0;l != c;++l) {
				add(dp[i][(j + l) % d][1], dp[i + 1][j][0]);
			}
			add(dp[i][(j + c) % d][0], dp[i + 1][j][0]);
			
			for (usize l = 0;l != 10;++l) {
				add(dp[i][(j + l) % d][1], dp[i + 1][j][1]);
			}
		}
	}

	std::cout << (dp[0][0][0] + dp[0][0][1] + MOD - 1) % MOD << std::endl;

	return 0;
}


Compiler output:
a.cc:34:19: error: explicit specialization in non-namespace scope 'class multi_dimensional_vector<T, Dimension>'
   34 |         template <> class mdv_inner<static_cast<std::size_t>(1)> {
      |                   ^
a.cc:34:27: error: too few template-parameter-lists
   34 |         template <> class mdv_inner<static_cast<std::size_t>(1)> {
      |                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.cc: In function 'int main()':
a.cc:81:23: error: no match for 'operator=' (operand types are 'multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>' and 'int')
   81 |         dp[n][0][0] = 1;
      |                       ^
a.cc:20:40: note: candidate: 'constexpr multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>& multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>::operator=(const multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>&)'
   20 |         template <std::size_t D> class mdv_inner {
      |                                        ^~~~~~~~~
a.cc:20:40: note:   no known conversion for argument 1 from 'int' to 'const multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>&'
a.cc:20:40: note: candidate: 'constexpr multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>& multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>::operator=(multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>&&)'
a.cc:20:40: note:   no known conversion for argument 1 from 'int' to 'multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>&&'
a.cc:91:36: error: no match for call to '(const main()::<lambda(u32&, const u32&)>) (multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>, multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>)'
   91 |                                 add(dp[i][(j + l) % d][1], dp[i + 1][j][0]);
      |                                 ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.cc:91:36: note: candidate: 'void (*)(u32&, const u32&)' {aka 'void (*)(unsigned int&, const unsigned int&)'} (conversion)
a.cc:91:36: note:   candidate expects 3 arguments, 3 provided
a.cc:83:24: note: candidate: 'main()::<lambda(u32&, const u32&)>'
   83 |         const auto add=[](u32 &l, const u32 &r) {
      |                        ^
a.cc:83:24: note:   no known conversion for argument 1 from 'multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>' to 'u32&' {aka 'unsigned int&'}
a.cc:93:28: error: no match for call to '(const main()::<lambda(u32&, const u32&)>) (multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>, multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>)'
   93 |                         add(dp[i][(j + c) % d][0], dp[i + 1][j][0]);
      |                         ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.cc:93:28: note: candidate: 'void (*)(u32&, const u32&)' {aka 'void (*)(unsigned int&, const unsigned int&)'} (conversion)
a.cc:93:28: note:   candidate expects 3 arguments, 3 provided
a.cc:83:24: note: candidate: 'main()::<lambda(u32&, const u32&)>'
   83 |         const auto add=[](u32 &l, const u32 &r) {
      |                        ^
a.cc:83:24: note:   no known conversion for argument 1 from 'multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>' to 'u32&' {aka 'unsigned int&'}
a.cc:96:36: error: no match for call to '(const main()::<lambda(u32&, const u32&)>) (multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>, multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>)'
   96 |                                 add(dp[i][(j + l) % d][1], dp[i + 1][j][1]);
      |                                 ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.cc:96:36: note: candidate: 'void (*)(u32&, const u32&)' {aka 'void (*)(unsigned int&, const unsigned int&)'} (conversion)
a.cc:96:36: note:   candidate expects 3 arguments, 3 provided
a.cc:83:24: note: candidate: 'main()::<lambda(u32&, const u32&)>'
   83 |         const auto add=[](u32 &l, const u32 &r) {
      |                        ^
a.cc:83:24: note:   no known conversion for argument 1 from 'multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>' to 'u32&' {aka 'unsigned int&'}
a.cc:101:35: error: no match for 'operator+' (operand types are 'multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>' and 'multi_dimensional_vector<unsigned int, 3>::mdv_inner<0>')
  101 |         std::cout << (dp[0][0][0] + dp[0][0][1] + MOD - 1) % MOD << std::endl;
      |                       ~~~~~~~~~~~ ^ ~~~~~~~~~~~
      |                                 |             |
      |                                 |             mdv_inner<[...]>
      |                                 mdv_inner<[...]>