每个位置显然是先变成正确的,然后进去若干循环
这样就可以算出最多进行多少轮变换,
令
fi,j,k
表示进行了
i
轮变换,有
直接DP肯定不行,可以用矩乘优化
// BEGIN CUT HERE
// END CUT HERE
#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 <queue>
#include <assert.h>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=256,P=1e9+7;
int n,m,S;
int c[3][3];
int u[N][N],f[N][N];
inline void mul(int a[][N],int b[][N],int c[][N]){
static int tmp[N][N];
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=S;i++)
for(int j=1;j<=S;j++)
for(int k=1;k<=S;k++)
tmp[i][j]=(tmp[i][j]+1LL*a[i][k]*b[k][j])%P;
memcpy(c,tmp,sizeof(tmp));
}
inline void Pow(int a[][N],int y,int b[][N]){
static int tmp1[N][N];
memset(tmp1,0,sizeof(tmp1));
for(int i=1;i<=S;i++) tmp1[i][i]=1;
for(;y;y>>=1,mul(a,a,a)) if(y&1) mul(a,tmp1,tmp1);
memcpy(b,tmp1,sizeof(tmp1));
}
inline int g(int x,int y){
return x*(n+1)+y+1;
}
inline int dis(char a,char b){
if(a==b) return 0;
if(a=='a' && b=='b') return 1;
if(a=='b' && b=='c') return 1;
if(a=='c' && b=='a') return 1;
return 2;
}
class ConversionMachine{
public:
int countAll(string word1, string word2, vector <int> costs, int maxCost){
memset(u,0,sizeof(u)); memset(f,0,sizeof(f));
n=word1.size(); ll cur=0,cc=costs[0]+costs[1]+costs[2];
c[0][1]=costs[0]; c[1][2]=costs[1]; c[2][0]=costs[2];
c[0][2]=c[0][1]+c[1][2]; c[1][0]=c[1][2]+c[2][0]; c[2][1]=c[2][0]+c[0][1];
for(int i=0;i<n;i++) cur+=c[word1[i]-'a'][word2[i]-'a'];
if(cur>maxCost) return 0;
m=(maxCost-cur)/cc*3; S=(n+1)*(n+1); S++;
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k++){
if(j<n) u[g(j,k)][g(j+1,k)]=j+1;
if(k) u[g(j,k)][g(j,k-1)]=n-j-k+1;
if(j && k<n) u[g(j,k)][g(j-1,k+1)]=k+1;
}
u[S][g(0,0)]=1;
u[S][S]=1;
int cj=0,ck=0;
for(int i=0;i<n;i++){
if(dis(word1[i],word2[i])==1) cj++;
if(dis(word1[i],word2[i])==2) ck++;
}
m+=cj+2*ck;
f[g(cj,ck)][1]=1;
Pow(u,m,u);
mul(u,f,f);
return (f[S][1]+f[g(0,0)][1])%P;
}
// BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { string Arg0 = "a"; string Arg1 = "b"; int Arr2[] = {100,2,3}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 205; int Arg4 = 2; verify_case(0, Arg4, countAll(Arg0, Arg1, Arg2, Arg3)); }
void test_case_1() { string Arg0 = "abcba"; string Arg1 = "abcba"; int Arr2[] = {67,23,43}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 0; int Arg4 = 1; verify_case(1, Arg4, countAll(Arg0, Arg1, Arg2, Arg3)); }
void test_case_2() { string Arg0 = "cccccccc"; string Arg1 = "aaaaaaaa"; int Arr2[] = {10000000,1,1}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 100; int Arg4 = 40320; verify_case(2, Arg4, countAll(Arg0, Arg1, Arg2, Arg3)); }
void test_case_3() { string Arg0 = "aa"; string Arg1 = "cc"; int Arr2[] = {1,10,100}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); int Arg3 = 1787; int Arg4 = 123611681; verify_case(3, Arg4, countAll(Arg0, Arg1, Arg2, Arg3)); }
// END CUT HERE
};
// BEGIN CUT HERE
int main()
{
ConversionMachine ___test;
___test.run_test(-1);
system("pause");
}
// END CUT HERE