• 【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 imes n^2$的。

    然后就做完了

    时间复杂度:$O(n^6log 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 }
  • 相关阅读:
    UVA 1386
    疯狂Android演讲2 环境配置
    七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)
    【iOS发展-44】通过案例谈iOS重构:合并、格式化输出、宏观变量、使用数组来存储数据字典,而且使用plist最终的知识
    jQuery选择
    一个月操作总结
    C++易vector
    oracle rac 在完成安装错误。
    NginX issues HTTP 499 error after 60 seconds despite config. (PHP and AWS)
    解决Eclipse中文乱码的方法
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10397411.html
Copyright © 2020-2023  润新知