#include #include #include #include #include //#include using namespace std; const int maxm = 500 + 1; const int maxp = 50 + 1; const int MOD = 998244353; int n, p, m; int f[maxp][maxp][maxm], g[11][maxm][maxm]; void add(int &a, int b) { a += b; if (a >= MOD) { a -= MOD; } } int powmod(int a, int b) { if (b == 0) { return 1; } int ret = powmod(a, b >> 1); ret = (long long)ret * ret % MOD; if (b & 1) { ret = (long long)ret * a % MOD; } return ret; } int temp[maxm][maxm], ans[2][maxm][maxm], mat[maxm][maxm]; void mul(int a[maxm][maxm], int b[maxm][maxm], int c[maxm][maxm], int m) { memset(temp, 0, sizeof(temp)); for (int i = 0; i < m; ++ i) { int *tempi = temp[i]; for (int k = i; k < m; ++ k) { long long x = b[i][k]; if (!x) { continue; } for (int j = k; j < m; ++ j) { tempi[j] += x * c[k][j] % MOD; tempi[j] %= MOD; } } } for (int i = 0; i < m; ++ i) { for (int j = i; j < m; ++ j) { a[i][j] = temp[i][j]; } } } int main() { assert(scanf("%d%d%d", &n, &p, &m) == 3 && 1 <= n && n <= 1000000000 && 1 <= p && p <= 50 && 1 <= m && m <= 500); int cnt[p]; memset(cnt, 0, sizeof(cnt)); if (n <= p) { int mul = 1 % p; for (int i = 0; i < n; ++ i) { cnt[mul] += 1; mul = mul * 10 % p; } } else { int mark[p], value[p]; memset(mark, -1, sizeof(mark)); int mul = 1 % p; for (int i = 0; i < n; ++ i) { if (mark[mul] != -1) { int period = i - mark[mul]; for (int delta = 0; delta < period; ++ delta) { int times = (n - i) / period + ((n - i) % period > delta); cnt[value[mark[mul] + delta]] += times; } break; } else { value[i] = mul; ++ cnt[mul]; mark[mul] = i; } mul = mul * 10 % p; } } vector totals, types; for (int i = 0; i < p; ++ i) { if (cnt[i] > 0) { //fprintf(stderr, "i = %d, cnt = %d\n", i, cnt[i]); totals.push_back(cnt[i]); types.push_back(i); } } sort(totals.begin(), totals.end()); totals.erase(unique(totals.begin(), totals.end()), totals.end()); //fprintf(stderr, "size totals = %d\n", (int) totals.size()); assert(totals.size() <= 2); int plans[totals.size()][m + 1]; int rev[m + 1]; for (int i = 1; i <= m; ++ i) { rev[i] = powmod(i, MOD - 2); } for (int type = 0; type < totals.size(); ++ type) { int total = totals[type]; memset(g, 0, sizeof(g)); g[1][0][0] = 1; for (int d = 1; d < 10; ++ d) { for (int changed = 0; changed <= m; ++ changed) { for (int cost = changed; cost <= m; ++ cost) { if (g[d][changed][cost] == 0) { continue; } long long comb = 1; int remain = total - changed; for (int num = 0; num * d + cost <= m; ++ num) { add(g[d + 1][changed + num][cost + num * d], g[d][changed][cost] * comb % MOD); comb = comb * remain % MOD * rev[num + 1] % MOD; -- remain; } } } } for (int i = 0; i <= m; ++ i) { int &sum = plans[type][i]; sum = 0; for (int changed = 0; changed <= i; ++ changed) { sum += g[10][changed][i]; sum %= MOD; } /*if (i == 1) { fprintf(stderr, "%d %d\n", i, plans[type][i]); }*/ } } /*memset(mat, 0, sizeof(mat)); memset(ans, 0, sizeof(ans)); for (int i = 0; i <= m; ++ i) { for (int j = 0; j < 10 && i + j <= m; ++ j) { mat[i][i + j] = 1; } for (int j = 0; j < totals.size(); ++ j) { ans[j][i][i] = 1; } } vector remain = totals; while (true) { bool end = true; for (int i = 0; i < remain.size(); ++ i) { int &total = remain[i]; //fprintf(stderr, "%d\n", total); if (total & 1) { mul(ans[i], ans[i], mat, m + 1); } if (total != 0) { end = false; total >>= 1; } } if (end) { break; } mul(mat, mat, mat, m + 1); } for (int type = 0; type < totals.size(); ++ type) { for (int i = 0; i <= m; ++ i) { plans[type][i] = ans[type][0][i]; //fprintf(stderr, "%d %d\n", i, plans[type][i]); } }*/ //fprintf(stderr, "phase 1 done: %.10f\n", clock() / CLOCKS_PER_SEC); memset(f, 0, sizeof(f)); f[0][0][0] = 1; for (int i = 0; i < types.size(); ++ i) { int type = types[i], total_type; if (cnt[type] == totals[0]) { total_type = 0; } else { total_type = 1; } for (int mod = 0; mod < p; ++ mod) { for (int cost = 0; cost <= m; ++ cost) { if (f[i][mod][cost] == 0) { continue; } long long value = f[i][mod][cost]; int new_mod = mod; for (int delta = 0; cost + delta <= m; ++ delta) { int plan = plans[total_type][delta]; if (plan == 0) { continue; } plan = plan * value % MOD; //fprintf(stderr, "%d %d %d: %d, delta = %d, type = %d\n", i, mod, cost ,f[i][mod][cost], delta, type); add(f[i + 1][new_mod][cost + delta], plan); new_mod += type; if (new_mod >= p) { new_mod -= p; } } } } } //fprintf(stderr, "types size = %d\n", types.size()); int sum = 0; for (int cost = 0; cost <= m; ++ cost) { add(sum, f[types.size()][0][cost]); //fprintf(stderr, "(%d)", f[types.size()][0][cost]); printf("%d%c", sum, cost == m ? '\n' : ' '); } return 0; }