「2017 山东一轮集训 Day6」子序列(矩阵快速幂)

it2022-05-06  2

/* 找出了一个dp式子 是否能够倍增优化 我推的矩阵不太一样 是 1 0 0 0 0 0 0 0 0 -1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 2 求得逆矩阵大概就是 1 0 0 0 0 0 2 0 0 1 0 0 1 0 0 0 0 0 1 0 0 -1 0 0 0 */ #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<queue> #define ll long long #define M 100010 #define log lllgggi #define mmp make_pair using namespace std; int read() { int nm = 0, f = 1; char c = getchar(); for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0'; return nm * f; } const int mod = 1000000007; char s[M]; void add(int &x, int y) { x += y; x -= x >= mod ? mod : 0; x += x < 0 ? mod : 0; } struct Mx{ int a[10][10]; Mx() { memset(a, 0, sizeof(a)); } }be[9], iv[9], an[M], bn[M]; Mx mul(Mx a, Mx b) { Mx c; for(int i = 0; i <= 9; i++) { for(int j = 0; j <= 9; j++) { for(int k = 0; k <= 9; k++) { add(c.a[i][k], 1ll * a.a[i][j] * b.a[j][k] % mod); } } } return c; } int n, a[M], sum, q, f[10], g[10]; int main() { scanf("%s", s + 1); n = strlen(s + 1); for(int i = 1; i <= n; i++) a[i] = s[i] - 'a'; for(int k = 0; k <= 8; k++) { for(int i = 0; i <= 8; i++) { if(i == k) { be[k].a[9][k] = 1; be[k].a[k][9] = mod - 1; iv[k].a[i][i] = 2; iv[k].a[i][9] = 1; iv[k].a[9][i] = mod - 1; } else { be[k].a[i][i] = 1; iv[k].a[i][i] = 1; } } be[k].a[9][9] = 2; } for(int i = 0; i <= 9; i++) an[0].a[i][i] = bn[0].a[i][i] = 1; for(int i = 1; i <= n; i++) an[i] = mul(an[i - 1], be[a[i]]), bn[i] = mul(iv[a[i]], bn[i - 1]); q = read(); while(q--) { int l = read(), r = read(); memset(f, 0, sizeof(f)); f[9] = 1; memset(g, 0, sizeof(g)); for(int i = 0; i <= 9; i++) { for(int j = 0; j <= 9; j++) { add(g[i], 1ll * f[j] * bn[l - 1].a[j][i] % mod); } } memcpy(f, g, sizeof(f)); int ans = 0; for(int j = 0; j <= 9; j++) { add(ans, 1ll * f[j] * an[r].a[j][9] % mod); } cout << (ans - 1 + mod) % mod << "\n"; } return 0; }

转载于:https://www.cnblogs.com/luoyibujue/p/10619055.html


最新回复(0)