CF_137_div2_E_Decoding Genome 题解

来源:互联网 发布:linux公社 ftp 编辑:程序博客网 时间:2024/05/21 18:00

Brief Description:

一个字符串由n个字符组成,字符只能是大小写的字母(a->z,A->Z),其中a对应0,b对应1.....z对应25,A对应26,B对应27,Z对应51,且字符只能取编号0->m,现在规定某2个字符不能靠在一起,求这样的字符串有多少个。

Analysis:

先不考虑题目的规模,我们定义sum[i][j]:取前i个字符,第i个字符时j,能组成多少个字符串

则有sum[i][j] = sigma(sum[i-1][k]) 且k,j可以靠在一起,时间复杂度为O(26*n).

由于n <= 1e+15,这么做会超时 ,所以只能另辟蹊径!

怎么做呢?线性操作可以考虑矩阵快速幂~正解就是矩阵快速幂。

我们知道sum[1][j] = 1。 0<=j<m

定义矩阵M = (num[i][j]),若i,j可以靠在一起,num[i][j]=1,否则num[i][j]=0

我们用矩阵ansM=(sum[1][0],sum[1][1]....sum[1][m-1])*M^n-1,ansM的第i列数总和就是sum[n][i],

最后我们只需将ansM中的所有数加起来便是答案。

源代码如下:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#define M 1000000007using namespace std;typedef long long LL;struct Matrix{    LL num[64][64];};LL n;int m,K;LL G[64][64];Matrix mul(Matrix p,Matrix q) {     Matrix ret;     for(int i=0; i<m; i++) for(int j=0; j<m; j++) {        ret.num[i][j] = 0;        for(int k=0; k<m; k++) {           ret.num[i][j] += p.num[i][k] * q.num[k][j];           ret.num[i][j] %= M;        }     }     return ret;}Matrix f(){    Matrix ret,p;    memset(ret.num,0,sizeof(ret.num));    for(int i=0; i<m; i++) ret.num[i][i] = 1;    for(int i=0; i<m; i++) for(int j=0; j<m; j++) p.num[i][j] = G[i][j];    n--;    while(n)    {        if(n & 1)          ret = mul(ret,p);        p = mul(p,p);        n >>= 1;    }    return ret;}int main(){    while(scanf("%I64d%d%d",&n,&m,&K) == 3)    {        int i,j;        for(i=0; i<m; i++) for(j=0; j<m; j++) G[i][j] = 1;        while(K--)        {            char c1,c2;            int x,y;            scanf(" %c %c",&c1,&c2);            x = c1>='a'&&c1<='z'?c1-'a':c1-'A'+26;            y = c2>='a'&&c2<='z'?c2-'a':c2-'A'+26;            G[x][y] = 0;        }        Matrix ansM = f();      //  for(i=0; i<m; i++)        LL ans = 0;        for(i=0; i<m; i++)        {            for(j=0; j<m; j++)            {                ans += ansM.num[i][j];                ans %= M;            }        }        printf("%I64d\n",ans);    }    return 0;}

原创粉丝点击