题解:CF1895F Fancy Arrays
ka_da_Duck · · 题解
题意就是让你求出有多少个长度为
我们先看“并且至少有一个数属于
用容斥原理转化一下,我们就可以,用
(I) 看 \min_{i=1}^{n}a_i\le x+k-1 的方案总数如何求
我们发现只要确定了
因为
(II) 看 \max_{i=1}^na_i< x 的方案总数如何求
后者就是要求出
令
定义初始一个
得到了两部分的答案,减一下就可以了,时间复杂度
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 40 + 5, mod = 1e9 + 7;
int n, x, k;
struct Matrix{
int a[maxn][maxn];
friend Matrix operator * (const Matrix &u, const Matrix &v) {
Matrix res;
memset(res.a, 0, sizeof res.a);
for (int k = 1; k <= x; ++k)
for (int i = 1; i <= x; ++i)
for (int j = 1; j <= x; ++j)
res.a[i][j] = (res.a[i][j] + u.a[i][k] * v.a[k][j]) % mod;
return res;
}
} r1, r2;
int qpow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = res * a % mod;
b >>= 1, a = a * a % mod;
}
return res;
}
void mpow(int k) {
while (k) {
if (k & 1) r1 = r1 * r2;
r2 = r2 * r2, k >>= 1;
}
}
void solve() {
cin >> n >> x >> k;
int ans = qpow(2 * k + 1, n - 1) * (x + k) % mod;
for (int i = 1; i <= x; ++i) r1.a[1][i] = 1;
for (int i = 1; i <= x; ++i) for (int j = 1; j <= x; ++j) r2.a[i][j] = (abs(i - j) <= k);
mpow(n - 1);
for (int i = 1; i <= x; ++i) ans = (ans - r1.a[1][i] + mod) % mod;
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) solve();
}