码迷,mamicode.com
首页 > 其他好文 > 详细

hdu2604 递推转换矩阵快速幂

时间:2015-07-15 12:37:47      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:

      刚开始还以为用位运算与或几下几个循环就搞定了,算着算着发现不行........

      还是一种固定的切题角度,我假设有长度为n,总的排列数位f(n),怎么算他呢?从后往前考虑,因为大多数情况,都是用前面的结果推后面的结果, 那么当第n位是m的时候,如果我知道f(n-1)等于多少,那么f(n-1)的排列+加一个m是不是就是f(n)的一部分解了?  对吧,以此类推,   当第n位为f的时候,可是fff,fmf不能连着 那是不是就剩下ffm,fmm的情况了,对于前者ffm,由于不能凑成ffmf的情况,所以只能是f(n-4). 对于后者fmm,无论邻接m的是什么都不会冲突,所以有f(n-3).至此全了,第n位的所有情况都考虑到了,那么就算出了以下公式:

                                                                                       f(n)=f(n-1)+f(n-3)+f(n-4)

      写出代码拍上去发现超时了..........莫办法只能矩阵优化一下看看了.

      我们设 有矩阵A  使  (f[n],f[n-1],f[n-2],f[n-3]) = (f[n-1],f[n-2],f[n-3],f[n-4])*A成立 

      求出A={{1,0,1,1},{1,0,0,0},{0,1,0,0},{0,0,1,0}}

      所以有 (f[n],f[n-1],f[n-2],f[n-3])=(f[1],f[2],f[3],f[4])*A的n-4次幂

      上代码

   

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 
 7 int answer[5];
 8 struct mac
 9 {
10     int m[4][4];
11 };
12 mac power(mac x,mac y,int p)
13 {
14     mac temp;
15     for(int i=0;i<4;i++)
16     {
17         for(int j=0;j<4;j++)
18         {
19             temp.m[i][j]=0;
20             for(int k=0;k<4;k++)
21                 temp.m[i][j]=(temp.m[i][j]+x.m[i][k]*y.m[k][j])%p;
22         }
23     }
24     return temp;
25 }
26 void eachother(int n,int k)
27 {
28     mac pri,unit;
29     memset(unit.m,0,sizeof(unit.m));
30     memset(pri.m,0,sizeof(pri.m));
31     unit.m[0][0]=unit.m[1][1]=unit.m[2][2]=unit.m[3][3]=1;
32     pri.m[0][0]=pri.m[0][2]=pri.m[0][3]=pri.m[1][0]=pri.m[2][1]=pri.m[3][2]=1;
33     while(n)
34     {
35         if(n&1)
36         {
37             unit = power(unit,pri,k);
38         }
39         pri = power(pri,pri,k);
40         n >>= 1;
41     }
42     int ans = (answer[4]*unit.m[0][0]+answer[3]*unit.m[0][1]+answer[2]*unit.m[0][2]+answer[1]*unit.m[0][3])%k;
43     printf("%d\n",ans);
44 }
45 int main()
46 {
47     int n,k;
48     while(scanf("%d%d",&n,&k)!=EOF)
49     {
50         memset(answer,0,sizeof(answer));
51         answer[1]=2;
52         answer[2]=4;
53         answer[3]=6;
54         answer[4]=9;
55         if(n<=4)
56         {
57             printf("%d\n",answer[n]%k);
58         }
59         else{
60            eachother(n-4,k);
61         }
62     }
63     return 0;
64 }

 

hdu2604 递推转换矩阵快速幂

标签:

原文地址:http://www.cnblogs.com/tenlee/p/4647707.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!