细胞 (cell) 矩阵快速幂
细胞 (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
1.2 30 分做法
直接使用上述公式暴力递推,复杂度 O(n) 。
1.3 40 分做法
对于 x = 1 的情况,即为求 1 n 的和,直接输出即可。
1.4 100 分做法
使用矩阵快速幂优化递推。
矩阵大小为 3 *3 ,故复杂度为 O(27logn) 。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; typedef long long lol; lol n,x,w; lol gi() { lol ans=0,f=1; char i=getchar(); while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();} while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();} return ans*f; } struct matrix { lol a[3][3]; matrix(){for(int i=0;i<3;i++)for(int j=0;j<3;j++)a[i][j]=0;} matrix(lol b[3][3]){for(int i=0;i<3;i++)for(int j=0;j<3;j++)a[i][j]=b[i][j];} matrix operator *(matrix b) { matrix ans; for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++)ans.a[i][j]=(ans.a[i][j]+(a[i][k]*b.a[k][j])%w)%w; return ans; } }S,T; lol f(lol x,lol n) { lol a[3][3]={{0,1,1},{0,0,0},{0,0,0}},b[3][3]={{x,0,0},{1,1,0},{0,1,1}}; S=matrix(a);T=matrix(b); while(n) { if(n&1) { S=S*T; } T=T*T; n>>=1; } return S.a[0][0]; } int main() { int i,j; n=gi();x=gi();w=gi(); x%=w; printf("%lld",f(x,n)); return 0; }