hdu 1757 (矩阵快速幂) 一个简单的问题 一个简单的开始

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1757

题意不难理解,当x小于10的时候,数列f(x)=x,当x大于等于10的时候f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);

所求的是f(x)取m的模,而x,m,a[0]至a[9]都是输入项

初拿到这道题,最开始想的一般是暴力枚举,通过for循环求出f(x)然后再取模,但是有两个问题,首先f(x)可能特别大,其次是枚举超时。

所以,想到可以用到通过构造矩阵快速幂的方法。

稍微有点线性代数基础的人(比如本人)都知道可以构造一个10*10的矩阵

(10有点大,这里以3*3的代替,题意还是不变)

0  0  a0                                                0  0  a0    0  0  a0

(f0,f1,f2)*   1  0  a1 --->(f1,f2,f3)     然后(f0,f1,f2)* 1  0  a1 * 1  0  a1 --->(f2,f3,f4)

0  1  a2                                                0  1  a2    0  1  a2

0  0  a0   0  0  a0

最后一直到f(x)   (f0,f1,f2)* 1  0  a1* 1  0  a1*******--->(fx-2,fx-1,fx)

0  1  a2   0  1  a2

10*10的矩阵也基本很这个一样,然后光有矩阵并没有太大的卵用,还得用快速幂来取模,只不过换成了矩阵而已。

先开两个二维数组把矩阵给存起来(对,开两个存一模一样的矩阵,如果一下子没有反应过来为什么的等你写到这里的时候就知道为什么了)

然后第三个数组存相乘过程中的结果。(如果快速幂不会的请百度)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 long long jz1[11][11],jz2[11][11],jz3[11][11],i,j,k;
 6 long long a[11],m;
 7 long long lsy(long long n)
 8 {
 9     long long sum=0;
10     for (i=0;i<=9;i++){  //创建矩阵
11         for (j=0;j<=9;j++){
12             if (j!=9){
13                 if (i-j==1)
14                 {
15                     jz1[i][j]=1;
16                     jz2[i][j]=1;
17                 }
18                 else
19                 {
20                     jz1[i][j]=0;
21                     jz2[i][j]=0;
22                 }
23             }
24             else
25             {
26                 jz1[i][9]=a[9-i];
27                 jz2[i][9]=a[9-i];
28             }
29         }
30     }
31     n-=10;
32     while (n!=0)  //快速幂取模
33     {
34         if (n&1)
35         {
36             memset(jz3,0,sizeof(jz3));
37             for (i=0;i<=9;i++){
38                 for (j=0;j<=9;j++){
39                     for (k=0;k<=9;k++){
40                         jz3[i][j]+=jz1[i][k]*jz2[k][j]%m;
41                     }
42                 }
43             }
44             memcpy(jz2,jz3,sizeof(jz3));
45         }
46         memset(jz3,0,sizeof(jz3));
47             for (i=0;i<=9;i++){
48                 for (j=0;j<=9;j++){
49                     for (k=0;k<=9;k++){
50                         jz3[i][j]+=jz1[i][k]*jz1[k][j]%m;
51                     }
52                 }
53             }
54             memcpy(jz1,jz3,sizeof(jz3));
55             n>>=1;  //不要忘了
56     }
57     for (i=0;i<10;i++)
58          sum=(((i%m)*jz2[i][9])%m+sum)%m;
59     return sum;
60 }
61 int main()
62 {
63     long long n;
64     while (~scanf("%I64d %I64d",&n,&m))
65     {
66         if (n==0&&m==0) break;
67         for (i=0;i<=9;i++)
68             scanf("%l64d",&a[i]);
69         if (n>=10)
70             printf("%I64d\n",lsy(n));
71         else
72             printf("%I64d\n",n%m);
73     }
74     return 0;
75 }
时间: 2024-10-22 05:01:53

hdu 1757 (矩阵快速幂) 一个简单的问题 一个简单的开始的相关文章

hdu 1757 矩阵快速幂 **

一看正确率这么高,以为是水题可以爽一发,结果是没怎么用过的矩阵快速幂,233 题解链接:点我 1 #include<iostream> 2 #include<cstring> 3 const int N=10; 4 using namespace std; 5 int k,m; 6 struct Matrix{ 7 int map[N][N]; 8 }; 9 10 Matrix matrix; 11 12 void Initiate(){ 13 for(int i=0;i<N

HDU 4965 矩阵快速幂

顺手写了下矩阵类模板 利用到矩阵乘法的交换律 (A*B)^n == A * (B*A)^n-1 *B #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <utility> #include <stack> #includ

hdu 4965 矩阵快速幂 矩阵相乘性质

Fast Matrix Calculation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 170    Accepted Submission(s): 99 Problem Description One day, Alice and Bob felt bored again, Bob knows Alice is a gir

HDU 1575 &amp;&amp; 1757 矩阵快速幂&amp;&amp;构造矩阵入门

HDU 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2912    Accepted Submission(s): 2167 Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据.每组

HDU 5895 矩阵快速幂+高次幂取模

HDU 5895 Mathematician QSC 题意:已知f(n)=2*f(n-1)+f(n-2), g(n)=∑f(i)²(0<=i<=n), 给出n,x,y,s, 求x^(g(n*y))%(s+1); 思路:OEIS查到了g(n)=f(n)*f(n+1)/2, f(n)可以用矩阵快速幂求得, 有一个定理可以用于高次幂取模 x^n %k=x^(n%phi(k)+phi(k)) %k, 此处phi(x)为欧拉函数,但是在对幂次取模时存在一个除2, 又因为(a/b)%k=(a%bk)/b,

HDU 3221 矩阵快速幂+欧拉函数+降幂公式降幂

装载自:http://www.cnblogs.com/183zyz/archive/2012/05/11/2495401.html 题目让求一个函数调用了多少次.公式比较好推.f[n] = f[n-1]*f[n-2].然后a和b系数都是呈斐波那契规律增长的.需要先保存下来指数.但是太大了.在这里不能用小费马定理.要用降幂公式取模.(A^x)%C=A^(x%phi(C)+phi(C))%C(x>=phi(C)) Phi[C]表示不大于C的数中与C互质的数的个数,可以用欧拉函数来求. 矩阵快速幂也不

hdu 2842(矩阵快速幂+递推)

题意:一个中国环的游戏,规则是一个木棒上有n个环,第一个环是可以随意放上或拆下的,剩下的环x如果想放上或拆下必须前一个环x-1是放上的且前x-2个环全部是拆下的,问n个环最少多少次操作可以全部拆掉. 题解:需要进行递推,首先第一步肯定是要拆第n个环保证操作次数最少,因为后面的环是否存在对前面的环不造成影响,而先拆前面的如果要拆后面的环还是要把前面的放上,f(n)表示拆掉前n个环需要的最少操作次数,先拆第n个要拆前n-2个再拆第n个,花费f(n-2)+1,然后这时是00-0010,要拆第n-1个需

hdu 4291(矩阵快速幂 + 循环节)

题意:求s s = g(g(g(n))) mod 1000000007 其中g(n) g(n) = 3g(n - 1) + g(n - 2) g(1) = 1 g(0) = 0 题解:普通的矩阵快速幂会超时,看到别人的题解是需要计算循环节得到小的MOD从而减小计算量.1000000007太大,需要计算更小的一个循环节,新技能get. #include <stdio.h> #include <string.h> struct Mat { long long g[3][3]; }ori

HDU 1005矩阵快速幂解法 循环节解法

循环节解法: 对于公式 f[n] = A * f[n-1] + B * f[n-2]; 后者只有7 * 7 = 49 种可能,为什么这么说,因为对于f[n-1] 或者 f[n-2] 的取值只有 0,1,2,3,4,5,6 这7个数,A,B又是固定的,所以就只有49种可能值了.由该关系式得知每一项只与前两项发生关系,所以当连续的两项在前面出现过,由于公式不变,那么后面得到的一定是跟前面相重复的.所以这个时候循环节就出现了,注意循环节并不一定会是开始的 1,1:但1,1一定可以作为一个循环节,只不过