题目来源:http://codeforces.com/problemset/problem/1117/D
令f[i]表示到i的方案数,则可以转移f[i] = f[i-1] + f[i-m]。
这样可以建一个m×m的矩阵进行转移。
代码:
#include <bits/stdc++.h>
#define ll long long
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
const int maxn = 1e5 + 10;
using namespace std;
const ll mod = 1e9 + 7;
ll n, m;
struct matrix {
ll num[101][101];
matrix() { memset(num, 0, sizeof num); }
matrix operator*(const matrix &x) {
matrix c;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= m; ++j) {
for (int k = 1; k <= m; ++k) {
c.num[i][j] = (c.num[i][j] + num[i][k] * x.num[k][j]) % mod;
}
}
}
return c;
}
matrix &operator=(const matrix &x) {
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= m; ++j) {
num[i][j] = x.num[i][j];
}
}
return *this;
}
};
matrix pow_mod(matrix &x, ll k) {
matrix ans;
for (int i = 1; i <= m; ++i) {
ans.num[i][i] = 1;
}
while (k) {
if (k & 1)ans = ans * x;
x = x * x;
k >>= 1;
}
return ans;
}
int f[111];
int main() {
__;
cin >> n >> m;
if (m > n) {
cout << 1 << endl;
return 0;
}
for (int i = 1; i < m; ++i)f[i] = 1;
f[m] = 2;
matrix a;
a.num[1][1] = a.num[1][m] = 1;
for (int i = 2; i <= m; ++i) {
a.num[i][i - 1] = 1;
}
matrix b = pow_mod(a, n - m);
/* for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= m; ++j) {
cout << b.num[i][j] << ' ';
}
cout << endl;
}*/
ll ans = 0;
for (int i = 1; i <= m; ++i) {
ans += b.num[1][i] * f[m - i + 1];
ans %= mod;
}
cout << ans << endl;
return 0;
}