矩阵快速幂

一、快速幂

快速幂是一种用于快速计算出a^k\ mod \ p(因为a^k太大,通常需要对一个数取模)的算法。因为较为基础,在此不多做讲解。主要原理:a^k=a^{\frac{k}{2}}*a^{\frac{k}{2}}(k\ mod\ 2=0)a^k=a^{\frac{k}{2}}*a^{\frac{k}{2}}*a(k\ mod\ 2=1)a^k=1(k=0)。因为指数在每次运算中都会缩小一半,时间复杂度为O(log_{2}k)。代码如下。

ll ksm(ll a, ll k)
{
  ll res = 1;
  while(k)
  {
    if(k%2)  res=res*a%M;
    a = a*a%M;
    k = k/2;
   }
  return res;
}

 例题 1:    hdu

二、矩阵快速幂      不懂的可以参考:https://blog.csdn.net/wust_zzwh/article/details/52058209

模板

struct mat    //个人习惯用结构体
{
    ll a[10][10];
    mat()
    {
        mem(a);
    }
};

mat mul(mat A,mat B)    //两个矩阵相乘
{
    mat res;
    for(int i = 0; i < 10; i++)
        for(int j = 0; j < 10; j++)
            for(int k = 0; k < 10; k++)
                res.a[i][j] = (res.a[i][j]+A.a[i][k]*B.a[k][j])%m;
    return res;
}

mat pow(mat A, ll n)                  //矩阵A的n次方
{
    mat B;
    for(int i = 0; i < 10; i++)
        B.a[i][i] = 1;
    while(n)
    {
        if(n&1)
            B = mul(A,B);
        A = mul(A,A);
        n>>=1;
    }
    return B;
}    

例题1    hdu2276

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 #define mem(a) memset(a,0,sizeof(a))
 8 #define ll long long
 9 
10 char s[101];
11 int n;
12 struct mat
13 {
14     int a[101][101];
15     mat()
16     {
17         mem(a);
18     }
19 };
20 
21 mat mul(mat A,mat B)
22 {
23     mat res;
24     for(int i = 0; i < n; i++)
25         for(int j = 0; j < n; j++)
26             for(int k = 0; k < n; k++)
27                 res.a[i][j] = (res.a[i][j] + A.a[i][k]*B.a[k][j])%2;
28     return res;
29 }
30 
31 mat pow(mat A,int m)
32 {
33     mat B;
34     for(int i = 0; i < n; i++)
35         B.a[i][i] = 1;
36     while(m)
37     {
38         if(m&1)
39             B = mul(A,B);
40         A = mul(A,A);
41         m >>= 1;
42     }
43     return B;
44 }
45 int main()
46 {
47     int m;
48     while(~scanf("%d",&m)&&m)
49     {
50         scanf("%s",s);
51         n = strlen(s);
52         mat A;
53         A.a[0][n-1] = A.a[0][0] =  1;
54         for(int i = 1; i < n; i++)
55         {
56             A.a[i][i] = A.a[i][i-1] = 1;
57         }
58         mat B;
59         for(int i = 0; i < n; i++)
60         {
61             B.a[i][0] = s[i]-'0';
62         }
63         mat ans;
64         ans = pow(A,m);
65         ans = mul(ans,B);          //mul(a,b)!=mul(b,a);
66         for(int i = 0; i < n; i++)
67             printf("%d",ans.a[i][0]);
68         printf("\n");
69     }
70     return 0;
71 }
例题1

例题2    hdu2604

解析   给你一个只有f和m,长度为l的字符串,让你找出满题条件的串的个数对m取余的数。如果这个串中不含fff和fmf就说这个串是满足条件的。
假设现有长度为n的串s,f(n)是s串满足条件的答案。f(n)怎么推出来捏?
如果s的最后一位为m,那么就加上f(n-1),因为在长度为n-1的满足条件的串后面加上一个m所得到的串肯定也满足条件。
如果s的最后一位为f,那么s的最后三位只有mmf和mff两种情况!继续讨论!
如果s以mmf结尾,那么加上f(n-3),因为在长度为n-3的满足条件的串后面加上一个mmf所得到的串肯定也满足条件。
那如果s以mff结尾呢?向前思考一位,倒数第四位只能是m,也就是此时s是以mmff结尾的,再加上f(n-4)岂不是美滋滋?
综上f(n)=f(n-1)+f(n-3)+f(n-4)。

pic

 

posted on 2019-08-12 14:25  By_布衣  阅读(167)  评论(0编辑  收藏  举报

导航