【xsy1237】 字符转换 矩阵快速幂

题目大意:给你两个长度都为n,字符集为{a,b,c}的字符串S和T。

对于字符串S的任意一个字符,我们可以用cost[0]的代价,把字符a变成字符b。用cost[1]的代价,把字符b变成c,用cost[2]的代价,把字符c变成a。

问你在总代价不超过MaxCost的情况下,有多少种方法,使得字符串S与字符串T相同。

两种方法被认为是不同的,当且仅当操作序列的长度是不同的,或者某一步操作的字符不同。

数据范围:$n≤11$,$1≤cost≤10^9$,$0≤MaxCost≤10^9$。

 

我们先用最少的代价使得$S=T$。不妨设该过程耗费的代价为$MinCost$,操作步数为$MinK$。

我们不难发现,接下来如果某个位置的字符需要发生变化,则该字符必须变化一整圈(变化3次),花费为$cost[0]+cost[1]+cost[2]$。

那么,变化的圈数显然不会超过$(MaxCost-MinCost)/(cost[0]+cost[1]+cost[2])$,我们令该值为$K$。

 

令$f[X][i][j][k]$表示第$X$次操作时,串$S$满足有$i$个位置与串$T$相同,有$j$个位置需要转$1$次才能与$T$相同,有$k$个位置需转$2$次才能与$T$相同。

显然,我们可以用$f[X][i][j][k]$,去更新:$f[X+1][i-1][j+1][k],f[X+1][i][j-1][k+1],f[i+1][j][k-1]$

不难发现我们可以用矩阵快速幂来加速转移。

考虑到$f[X][i][j][k]$需满足$i+j+k=0$。不难发现矩阵大小上限是$n^2\times n^2$的。

然后就做完了

 

时间复杂度:$O(n^6\log\ \frac{MaxCost}{Cost})$

  1 #include<bits/stdc++.h>
  2 #define N 11
  3 #define M 82
  4 #define L long long
  5 #define MOD 1000000007
  6 #define A 'a'
  7 #define B 'b'
  8 #define C 'c'
  9 using namespace std;
 10 
 11 struct mat{
 12     L a[M][M]; int n,m;
 13     mat(){memset(a,0,sizeof(a)); n=m=0;}
 14     mat(int _n,int _m){n=_n; m=_m; memset(a,0,sizeof(a));}
 15     void dw(){
 16         memset(a,0,sizeof(a));
 17         for(int i=1;i<=n;i++) a[i][i]=1;
 18     }
 19     friend mat operator *(mat a,mat b){
 20         mat c=mat(a.n,b.m);
 21         for(int i=1;i<=a.n;i++)
 22         for(int j=1;j<=a.m;j++)
 23         for(int k=1;k<=b.n;k++){
 24             if(a.a[i][k]*b.a[k][j]){
 25                 int yxq;
 26                 yxq=234;
 27             }
 28             c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%MOD;
 29         }
 30         return c;
 31     }
 32     friend mat operator ^(mat a,int b){
 33         mat ans=mat(a.n,a.n); ans.dw();
 34         while(b){
 35             if(b&1) ans=ans*a;
 36             a=a*a; b>>=1;
 37         }
 38         return ans;
 39     }
 40 };
 41 mat S,sta;
 42 
 43 int c[128][128]={0},h[128][128]={0};
 44 
 45 
 46 int n,times=0,lim,k=0; char s[20]={0},t[20]={0};
 47 int Init(){
 48     scanf("%s%s",s,t); n=strlen(s);
 49     scanf("%d%d%d",&c[A][B],&c[B][C],&c[C][A]);
 50     c[A][C]=c[A][B]+c[B][C];
 51     c[B][A]=c[B][C]+c[C][A];
 52     c[C][B]=c[C][A]+c[A][B];
 53     h[A][B]=h[B][C]=h[C][A]=1;
 54     h[B][A]=h[C][B]=h[A][C]=2;
 55     scanf("%d",&lim);
 56     int dn=0;
 57     for(int i=0;i<n;i++){
 58         k+=h[s[i]][t[i]];
 59         dn+=c[s[i]][t[i]];
 60     }
 61     k+=(lim-dn)/(c[A][B]+c[B][C]+c[C][A])*3;
 62 }
 63 
 64 int id[N][N][N]={0},cnt=0;
 65 void BuildMatrix(){
 66     for(int i=0;i<=n;i++)
 67     for(int j=0;j<=n;j++)
 68     for(int k=0;k<=n;k++)
 69     if(i+j+k==n){
 70         id[i][j][k]=++cnt;
 71     }
 72     S=mat(cnt+1,cnt+1);
 73     
 74     sta=mat(1,cnt+1);
 75     int p[3]={0};
 76     for(int i=0;i<n;i++) p[h[t[i]][s[i]]]++;
 77     sta.a[1][id[p[0]][p[1]][p[2]]]=1;
 78     
 79     for(int i=0;i<=n;i++)
 80     for(int j=0;j<=n;j++)
 81     for(int k=0;k<=n;k++)
 82     if(i+j+k==n){
 83         int ID=id[i][j][k],P=0;
 84         
 85         if(i-1>=0) P=id[i-1][j+1][k]; else P=0;
 86         if(P) S.a[ID][P]=i;
 87         
 88         if(j-1>=0) P=id[i][j-1][k+1]; else P=0;
 89         if(P) S.a[ID][P]=j;
 90         
 91         if(k-1>=0) P=id[i+1][j][k-1]; else P=0;
 92         if(P) S.a[ID][P]=k;
 93     }
 94     S.a[cnt+1][cnt+1]=S.a[id[n][0][0]][cnt+1]=1;
 95 }
 96 
 97 int main(){
 98     Init();
 99     BuildMatrix();
100     S=S^k;
101     sta=sta*S;
102     cout<<(sta.a[1][cnt+1]+sta.a[1][id[n][0][0]])%MOD<<endl;
103 }
posted @ 2019-02-18 19:30  AlphaInf  阅读(204)  评论(0编辑  收藏  举报