【HDU 2855】 Fibonacci Check-up (矩阵乘法)

Fibonacci Check-up



Problem Description
Every ALPC has his own alpc-number just like alpc12, alpc55, alpc62 etc.
As more and more fresh man join us. How to number them? And how to avoid their alpc-number conflicted? 
Of course, we can number them one by one, but that’s too bored! So ALPCs use another method called Fibonacci Check-up in spite of collision. 

First you should multiply all digit of your studying number to get a number n (maybe huge).
Then use Fibonacci Check-up!
Fibonacci sequence is well-known to everyone. People define Fibonacci sequence as follows: F(0) = 0, F(1) = 1. F(n) = F(n-1) + F(n-2), n>=2. It’s easy for us to calculate F(n) mod m. 
But in this method we make the problem has more challenge. We calculate the formula , is the combination number. The answer mod m (the total number of alpc team members) is just your alpc-number.

 

Input
First line is the testcase T.
Following T lines, each line is two integers n, m ( 0<= n <= 10^9, 1 <= m <= 30000 )

 

Output
Output the alpc-number.

 

Sample Input
2 1 30000 2 30000

 

Sample Output
1 3

 

【题意】

  求S(n)=∑C[k][n]*Fibonacci(k) mod m(0<=k<=n)
  ( 0<= n <= 10^9, 1 <= m <= 30000 )

 

【分析】

  组合数和斐波那契数列都是很有特点的东西,然而我想了一会儿还是没有想出来。

  现在又懂得了一点,能写出递推式,像斐波那契数列一样的,它的第k项其实可以表示成矩阵的幂,即A^k,把它当成数一样考虑就很方便。

  对于组合数,二项式定理啊真是太厉害了。。终于有点懂母函数的思想啊....

  

图片转自:http://blog.csdn.net/hzh_0000/article/details/38171903

 

其实还有第二种方法,我没打,感觉我不太可能推出来。。

 

第一种方法代码如下:

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

 

2016-09-28 14:10:22

posted @ 2016-09-28 14:06  konjak魔芋  阅读(313)  评论(0编辑  收藏  举报