矩阵乘法
状态表示为[i][j][k]表示这一个串中已经匹配好的有i个,差两步的有j个,差一步的有k个,显然i+j+k=len。
len最多11,所以状态数最多不到80
构造矩阵就是(i,j,k)->(i-1,j+1,k) ,有i个选择,要乘以i,另外两个转移也是一样的
然后就是一共能走几步的问题,统计一下最少步数复原要走几步,花费cost。能走的步数就是 复原的步数+3*((最多花费-花费)/走三步的花费)
然后矩阵乘法就可以了。
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <cstring> using namespace std; class ConversionMachine { public: int countAll(string, string, vector<int> , int); }; long long pmod = 1000000007; int id[12][12][12]; int rid[100][3]; int ed; long long a[105][105], tmp[105][105], tr[105][105]; void mul(long long a[][105], long long b[][105]) { int i, j, k; memset(tmp, 0, sizeof(tmp)); for (i = 0; i < ed; ++i) { for (j = 0; j < ed; ++j) { for (k = 0; k < ed; ++k) { tmp[i][j] += a[i][k] * b[k][j]; tmp[i][j] %= pmod; } } } for (i = 0; i < ed; ++i) { for (j = 0; j < ed; ++j) a[i][j] = tmp[i][j]; } } int ConversionMachine::countAll(string word1, string word2, vector<int> costs, int maxCost) { int i, j, k, n = word1.size(); int ii, jj, kk; long long cost = 0; int step = 0; ii = jj = kk = 0; for (i = 0; i < word1.size(); ++i) { if (word1[i] == 'a') { if (word2[i] == 'b') { cost += costs[0]; step++; kk++; } else if (word2[i] == 'c') { cost += costs[0] + costs[1]; step += 2; jj++; } else ii++; } if (word1[i] == 'b') { if (word2[i] == 'c') { cost += costs[1]; step++; kk++; } else if (word2[i] == 'a') { cost += costs[1] + costs[2]; step += 2; jj++; } else ii++; } if (word1[i] == 'c') { if (word2[i] == 'a') { cost += costs[2]; step++; kk++; } else if (word2[i] == 'b') { cost += costs[2] + costs[0]; step += 2; jj++; } else ii++; } } if (maxCost < cost) return 0; step += ((maxCost - cost) / (costs[0] + costs[1] + costs[2])) * 3; ed = 0; for (i = 0; i <= n; ++i) { for (j = 0; i + j <= n; ++j) { k = n - i - j; id[i][j][k] = ed; rid[ed][0] = i; rid[ed][1] = j; rid[ed][2] = k; ed++; } } memset(a, 0, sizeof(a)); ed++; for (i = 0; i < ed; ++i) a[i][i] = 1; memset(tr, 0, sizeof(tr)); for (i = 0; i < ed - 1; ++i) { int pi, pj, pk; pi = rid[i][0]; pj = rid[i][1]; pk = rid[i][2]; if (pi > 0) tr[i][id[pi - 1][pj + 1][pk]] += pi; if (pj > 0) tr[i][id[pi][pj - 1][pk + 1]] += pj; if (pk > 0) tr[i][id[pi + 1][pj][pk - 1]] += pk; } tr[ed - 1][ed - 1] = 1; tr[ed - 1][id[ii][jj][kk]] = 1; step++; while (step) { if (step & 1) mul(a, tr); mul(tr, tr); step >>= 1; } return a[ed - 1][id[n][0][0]]; }