#include #include #include // Používáme 32 bitů široká čísla, do kterých se vejdou naše výsledky. // Při násobení matic ale potřebujeme mezivýsledky před vymodulením // ukládat do 64-bitových integerů: násobení 32-bitových čísel může // dát až takhle velký výsledek. #include #include #define MOD 1000000007 void multiply_matrix(int32_t N, const int32_t* a, const int32_t* b, int32_t* output) { int32_t i, j, k; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { output[i*N + j] = 0; for (k = 0; k < N; k++) { int64_t A = a[i*N + k]; int64_t B = b[k*N + j]; // Tady je potřeba dát pozor na velikost datového typu. int64_t X = (A * B) % MOD; output[i*N + j] += X; output[i*N + j] %= MOD; } } } } void multiply_with_selector_matrix(int32_t N, int32_t I, const int32_t* b, int32_t* output) { // Vynásobí matici B maticí, která posouvá o I dní. // Nepotřebuju ji nikde explicitně mít. int32_t i, j; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { int32_t l = i - I, r = i + I; l = (N + (l % N)) % N; r %= N; output[i*N + j] = (b[l*N + j] + b[r*N + j]) % MOD; } } } void set_identity(int32_t N, int32_t* mat) { int32_t i, j; for (i = 0; i < N; i++) for (j = 0; j < N; j++) mat[i*N + j] = (i == j) ? 1 : 0; } int32_t* alloc_matrix(int32_t N) { return malloc(sizeof(int32_t) * N * N); } void copy_matrix(int32_t N, int32_t* dest, const int32_t* src) { memcpy(dest, src, sizeof(int32_t) * N * N); } void matrix_power(int32_t N, int32_t* base, int32_t exp, int32_t* result) { set_identity(N, result); int32_t* tmp = alloc_matrix(N), *tmp2 = alloc_matrix(N); copy_matrix(N, tmp, base); int32_t i; // Rychlé mocnění jako v kuchařce o teorii čísel. for (i = 1; i <= exp; i <<= 1) { if (exp & i) { multiply_matrix(N, tmp, result, tmp2); copy_matrix(N, result, tmp2); } multiply_matrix(N, tmp, tmp, tmp2); copy_matrix(N, tmp, tmp2); } free(tmp); free(tmp2); } int32_t find_ways(int32_t N, int32_t K) { int32_t i; int32_t* rm = alloc_matrix(N); // Matice číslo I posouvá o I dní. int32_t* tmp = alloc_matrix(N); // Matice číslo I posouvá o 1, 2, ..., I dní. // Pamatuju si jenom matici číslo N a matici číslo K % N. int32_t* n_steps = alloc_matrix(N); int32_t* k_steps = alloc_matrix(N); set_identity(N, n_steps); for (i = 1; i < N+1; i++) { if (i - 1 == K % N) { copy_matrix(N, k_steps, n_steps); } multiply_with_selector_matrix(N, i, n_steps, tmp); copy_matrix(N, n_steps, tmp); } // Vyšplhej do K - (K % N) dní matrix_power(N, n_steps, K / N, rm); // Ještě vynásob zbytkem do K. multiply_matrix(N, k_steps, rm, tmp); int32_t result = tmp[0]; free(rm); free(tmp); free(n_steps); free(k_steps); return result; } int main(int argc, char** argv) { (void) argc; (void) argv; FILE* in = fopen("ucetnictvi.in", "r"), *out = fopen("ucetnictvi.out", "w"); int32_t N, K; fscanf(in, "%" SCNd32 "%" SCNd32, &N, &K); fprintf(out, "%" PRId32 "\n", find_ways(N, K)); fclose(in); fclose(out); return 0; }