#include <iostream>
#include <vector>
using namespace std;
const long long MOD = 1e9 + 7;
long long power(long long base, long long exp) {
long long res = 1;
base %= MOD;
while (exp > 0) {
if (exp % 2 == 1) res = (res * base) % MOD;
base = (base * base) % MOD;
exp /= 2;
}
return res;
}
long long modInverse(long long n) {
return power(n, MOD - 2);
}
int main() {
// Optymalizacja wejścia/wyjścia
ios_base::sync_with_stdio(false);
cin.tie(NULL);
long long n, k, m;
if (!(cin >> n >> k >> m)) return 0;
long long invK = modInverse(k);
// Obliczanie prawdopodobieństw wejścia na pole v (p_v)
vector<long long> p(m);
p[0] = 1;
long long W = 0;
for (long long v = 1; v < m; ++v) {
W = (W + p[v - 1]) % MOD;
if (v - 1 - k >= 0) {
W = (W - p[v - 1 - k] + MOD) % MOD;
}
p[v] = (W * invK) % MOD;
}
// Obliczanie prawdopodobieństwa wygranej bezposrednio z pola v (q_v)
vector<long long> q(m);
for (long long v = 0; v < m; ++v) {
long long c = v + k - m + 1;
if (c < 0) c = 0;
if (c > k) c = k;
long long t_v = (c * invK) % MOD;
q[v] = (p[v] * t_v) % MOD;
}
// Obliczanie sufiksowych sum q_v (S_v) - prawdopodobieństwo zakończenia gry na >= v
vector<long long> S(m + 1, 0);
for (long long v = m - 1; v >= 0; --v) {
S[v] = (S[v + 1] + q[v]) % MOD;
}
// Obliczenie spodziewanej liczby rzutów
long long expected_rolls = 0;
for (long long v = 0; v < m; ++v) {
long long c = v + k - m + 1;
if (c < 0) c = 0;
if (c > k) c = k;
if (c > 0) {
// Wzór: (S[v]^n - (S[v] - q[v])^n) / t_v
long long inv_tv = (k * modInverse(c)) % MOD;
long long term1 = power(S[v], n);
long long S_minus_q = (S[v] - q[v] + MOD) % MOD;
long long term2 = power(S_minus_q, n);
long long diff = (term1 - term2 + MOD) % MOD;
long long term = (diff * inv_tv) % MOD;
expected_rolls = (expected_rolls + term) % MOD;
} else {
// Wzór graniczny: n * p_v * S_v^(n-1) (Gdy z bieżącego pola nie ma opcji zakończenia gry)
long long term = (n % MOD * p[v]) % MOD;
term = (term * power(S[v], n - 1)) % MOD;
expected_rolls = (expected_rolls + term) % MOD;
}
}
cout << expected_rolls << "\n";
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | #include <iostream> #include <vector> using namespace std; const long long MOD = 1e9 + 7; long long power(long long base, long long exp) { long long res = 1; base %= MOD; while (exp > 0) { if (exp % 2 == 1) res = (res * base) % MOD; base = (base * base) % MOD; exp /= 2; } return res; } long long modInverse(long long n) { return power(n, MOD - 2); } int main() { // Optymalizacja wejścia/wyjścia ios_base::sync_with_stdio(false); cin.tie(NULL); long long n, k, m; if (!(cin >> n >> k >> m)) return 0; long long invK = modInverse(k); // Obliczanie prawdopodobieństw wejścia na pole v (p_v) vector<long long> p(m); p[0] = 1; long long W = 0; for (long long v = 1; v < m; ++v) { W = (W + p[v - 1]) % MOD; if (v - 1 - k >= 0) { W = (W - p[v - 1 - k] + MOD) % MOD; } p[v] = (W * invK) % MOD; } // Obliczanie prawdopodobieństwa wygranej bezposrednio z pola v (q_v) vector<long long> q(m); for (long long v = 0; v < m; ++v) { long long c = v + k - m + 1; if (c < 0) c = 0; if (c > k) c = k; long long t_v = (c * invK) % MOD; q[v] = (p[v] * t_v) % MOD; } // Obliczanie sufiksowych sum q_v (S_v) - prawdopodobieństwo zakończenia gry na >= v vector<long long> S(m + 1, 0); for (long long v = m - 1; v >= 0; --v) { S[v] = (S[v + 1] + q[v]) % MOD; } // Obliczenie spodziewanej liczby rzutów long long expected_rolls = 0; for (long long v = 0; v < m; ++v) { long long c = v + k - m + 1; if (c < 0) c = 0; if (c > k) c = k; if (c > 0) { // Wzór: (S[v]^n - (S[v] - q[v])^n) / t_v long long inv_tv = (k * modInverse(c)) % MOD; long long term1 = power(S[v], n); long long S_minus_q = (S[v] - q[v] + MOD) % MOD; long long term2 = power(S_minus_q, n); long long diff = (term1 - term2 + MOD) % MOD; long long term = (diff * inv_tv) % MOD; expected_rolls = (expected_rolls + term) % MOD; } else { // Wzór graniczny: n * p_v * S_v^(n-1) (Gdy z bieżącego pola nie ma opcji zakończenia gry) long long term = (n % MOD * p[v]) % MOD; term = (term * power(S[v], n - 1)) % MOD; expected_rolls = (expected_rolls + term) % MOD; } } cout << expected_rolls << "\n"; return 0; } |
English