矩阵快速幂(快速幂)模板题目Decoding Genome

这类题目的难点在于,数据量大,需要用到高精度,也就是快速幂

矩阵的乘法与快速幂模板一:

const int mod = 1e9+7;
struct Matrix
{
	LL num[N][N];
};
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] = (ret.num[i][j] + p.num[i][k] * q.num[k][j]) % mod;
        }
     }
     return ret;
}

矩阵乘法与快速幂模板二:

ll c[N][N];
void mul(ll a[][N], ll b[][N])
{
	memset(c, 0, sizeof(c));
	for(int i=0;i<m;i++) 
		for(int j=0;j<m;j++)
			for(int k=0;k<m;k++)
				c[i][j] = (c[i][j]+c[i][k]+c[i][k])%mod;
	memcpy(a,c,sizeof(c));
}

例题:

https://codeforces.com/group/vFwRVj9WjO/contest/328371/problem/H

#include <bits/stdc++.h>
#define M 1000000007
using 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;
        // 最开始,所有的i和j都是可以连在一起的
        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();
        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;
}

第二个模板

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int i,j,k;
using namespace std;
#define N 100
#define MOD 1000000007
long long n;
int m;
int k;
int indice(char x)
{
    if(x>='a' && x<='z') return x-'a';
    else return x-'A'+26;
}//预处理字符转数字
 
long long c[N][N];
void cheng(long long a[][N],long long b[][N])
{
    memset(c,0,sizeof(c));
    for(int i=0; i<m; i++)
        for(int j=0; j<m; j++)
            for(int k=0; k<m; k++)
                c[i][j]=(c[i][j]+a[i][k]*b[k][j])%MOD;
    memcpy(a,c,sizeof(c)); // 这一步看似没太大必要
}
 
long long res[N][N];
long long odd[N][N];
 
void pow(long long p)
{
    memset(odd,0,sizeof(odd));
    for(int i=0; i<m; i++)
        odd[i][i]=1;
    if(p==0) // 如果是零次方,直接返回单位矩阵
    {
        memcpy(res,odd,sizeof(odd));
        return;
    }
    while(p>1) // 开始计算
    {
        if(p&1) 
            cheng(odd,res);
        cheng(res,res);
        p/=2;
    }
    cheng(res,odd);
}
 
string s;
int main()
{
    cin>>n>>m>>k;
    for(int i=0; i<m; i++)
        for(int j=0; j<m; j++)
            res[i][j]=1;
    for(int i=0; i<k; i++)
    {
        cin>>s;
        res[indice(s[0])][indice(s[1])]=0;
    }
    n--;
    pow(n);
    long long cont=0;
    for(int i=0; i<m; i++)
        for(int j=0; j<m; j++)
            cont=(cont+res[i][j])%MOD;
    cout<<cont<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值