CF1895F
Lightwhite · · 题解
portal
题意:求存在多少个长度为
注意到假设我们确定了差分数组和最小值,就可以得到整个序列的具体值。这是显然的,因为差分数组可以前缀和回去得到所有元素和
于是我们可以试求
发现这个东西很可 dp。由于序列中数的值域仅为
// STOOOOOOOOOOOOOOOOOOOOOOOOO hzt CCCCCCCCCCCCCCCCCCCCCCCORZ
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kX = 40 + 1, kP = 1e9 + 7;
int T;
int n, x, k;
struct Mat {
int a[kX][kX];
Mat() { fill(a[0], a[x] + x + 1, 0); }
Mat operator*(const Mat &o) const {
Mat ret;
for (int i = 0; i < x; i++) {
for (int k = 0; k < x; k++) {
for (int j = 0; j < x; j++) {
ret.a[i][j] = (ret.a[i][j] + 1ll * a[i][k] * o.a[k][j]) % kP;
}
}
}
return ret;
}
} a, ret;
int P(int a, int b) {
int ret = 1;
for (; b > 0; b /= 2) {
if (b & 1) {
ret = 1ll * ret * a % kP;
}
a = 1ll * a * a % kP;
}
return ret;
}
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> T;
while (T--) {
cin >> n >> x >> k;
int ans = 1ll * P(2 * k + 1, n - 1) * (x + k) % kP;
for (int i = 0; i < x; i++) {
for (int j = 0; j < x; j++) {
a.a[i][j] = (abs(i - j) <= k);
}
}
ret = Mat();
int b = n - 1;
for (int i = 0; i < x; i++) {
ret.a[0][i] = 1;
}
for (; b > 0; b /= 2) {
if (b & 1) {
ret = ret * a;
}
a = a * a;
}
for (int i = 0; i < x; i++) {
ans = (ans - ret.a[0][i] + kP) % kP;
}
cout << ans << '\n';
}
return 0;
}