题意:问长度在
[L,R]
之间的,且长度被
K
整除的,且仅包含
分析:考虑
dp
,
dp[i][0/1]
表示长度为
i
,最后一位字符是
转移:
dp[i][0]=dp[i−1][0]+dp[i−1][1],dp[i][1]=dp[i−1][0]
再用矩阵加速
dp
A=⎛⎝⎜110100001⎞⎠⎟,B=⎛⎝⎜100010111⎞⎠⎟
那么
ansR=⎛⎝⎜100000000⎞⎠⎟∗(AK∗B)R/K
再减去
L−1
的数量就是答案。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1
#define lll __int128;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 50010;
const int MAXM = 100005;
const ll MOD = 1000000007;
const double eps = 1e-8;
struct Mat {
ll edge[3][3];
friend Mat operator*(const Mat &a, const Mat &b) {
Mat c;
memset(c.edge, 0, sizeof(c.edge));
for (int i = 0; i<3; ++i) {
for (int j = 0; j<3; ++j) {
for (int k = 0; k<3; ++k) {
c.edge[i][j] += a.edge[i][k] * b.edge[k][j];
c.edge[i][j] %= MOD;
}
}
}
return c;
}
void print() {
for (int i = 0; i<3; ++i) {
for (int j = 0; j<3; ++j) {
printf("%I64d ", edge[i][j]);
}
printf("\n");
}
}
};
Mat qpow(Mat a, ll x) {
Mat res;
memset(res.edge, 0, sizeof(res.edge));
for (int i = 0; i<3; ++i)res.edge[i][i] = 1;
while (x) {
if (x & 1)res = res * a;
a = a * a;
x >>= 1;
}
return res;
}
int main() {
int T, cas = 0; scanf("%d", &T);
ll L, R, K;
while (T--) {
scanf("%I64d%I64d%I64d", &L, &R, &K);
Mat E;
memset(E.edge, 0, sizeof(E.edge));
E.edge[0][0] = 1;
Mat F, P;
memset(F.edge, 0, sizeof(F.edge));
F.edge[0][0] = F.edge[0][1] = F.edge[1][0] = 1;
F.edge[2][2] = 1;
F = qpow(F, K);
memset(P.edge, 0, sizeof(P.edge));
P.edge[0][2] = P.edge[1][2] = P.edge[2][2] = 1;
P.edge[0][0] = P.edge[1][1] = 1;
F = F * P;
//F.print();
Mat a = E * qpow(F, (L - 1) / K);
Mat b = E * qpow(F, R / K);
// b.print();
printf("Case %d: %I64d\n", ++cas, (b.edge[0][2] - a.edge[0][2] + MOD) % MOD);
}
}