细胞(cell) 矩阵快速幂

题目描述
小 X 在上完生物课后对细胞的分裂产生了浓厚的兴趣。于是他决定做实验并
观察细胞分裂的规律。
他选取了一种特别的细胞,每天每个该细胞可以分裂出 x 1 个新的细胞。
小 X 决定第 i 天向培养皿中加入 i 个细胞(在实验开始前培养皿中无细胞)。
现在他想知道第 n 天培养皿中总共会有多少个细胞。
由于细胞总数可能很多,你只要告诉他总数对 w 取模的值即可。
输入格式
第一行三个正整数 n; x; w。
输出格式
一行一个数表示第 n 天的细胞总数对 w 取模的值。
样例输入
2 2 47
样例输出
4
2
数据范围
对于 30% 的数据,n ≤10^7
对于另外 10% 的数据,x = 1
对于 100% 的数据,1≤n≤2^63-1    1≤x,w≤2^31-1

 

题解:

仔细想一想思路还是比较清晰的

首先递推式F[i]=x*F[i-1]+i 

那么需要转移的量为2个所以开三维,其中一维为i的辅助

可以写出:

F[i+1]  i+1  1 = F[i]  i  1     *     x 0 0

                                                   1 1 0

                                                   0 1 1

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 using namespace std;
 8 typedef long long ll;
 9 ll n,x,mod;
10 struct node{
11     ll a[3][3];
12     node(){for(int i=0;i<3;i++)for(int j=0;j<3;j++)a[i][j]=0;}
13     node(ll b[3][3]){for(int i=0;i<3;i++)for(int j=0;j<3;j++)a[i][j]=b[i][j];}
14     inline node operator *(const node p){
15         node tmp;
16         for(int i=0;i<3;i++)
17             for(int j=0;j<3;j++){
18                 tmp.a[i][j]=0;
19                 for(int k=0;k<3;k++)
20                     tmp.a[i][j]+=a[i][k]*p.a[k][j],tmp.a[i][j]%=mod;
21             }
22         return tmp;
23     }
24 };
25 ll work(){
26     ll t[3][3]={{0,1,1},{0,0,0},{0,0,0}},sum[3][3]={{x,0,0},{1,1,0},{0,1,1}};
27     node S=node(t),T=node(sum);
28     while(n){
29         if(n&1)S=S*T;
30         T=T*T;n>>=1;
31     }
32     return S.a[0][0];
33 }
34 int main()
35 {
36     freopen("cell.in","r",stdin);
37     freopen("cell.out","w",stdout);
38     scanf("%lld%lld%lld",&n,&x,&mod);
39     printf("%lld\n",work());
40     return 0;
41 }

 

 

 

 

posted @ 2017-07-09 22:31  PIPIBoss  阅读(216)  评论(0编辑  收藏  举报