水平太渣. 唯有看完解题报告+标程 AK这套题.
需要取上整,核心点加上了一个小于1的小数.
当n = 2时,有 , 然后可以验证下当n取其他值时也满足。所以就有
又 , 则其特征方程的两个解为:
当 n = 2. 时, 其特征方程为:
化简得到:
因为
所以有:
S_2 - 2*a*S_1 + (a^2+b) = 0
得到线性递推关系, 然后矩阵快速幂随便搞搞就好了。
// Sn = ceil( [a + sqrt(b)]^n ) % m; #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; struct Matrix{ LL mat[2][2]; void zero(){memset(mat,0,sizeof(mat));} void unit(){zero();mat[0][0]=mat[1][1]=1;} }A,T; Matrix mult( Matrix a, Matrix b, int mod ){ Matrix c; c.zero(); for(int i = 0; i < 2; i++) for(int k = 0; k < 2; k++) for(int j = 0; j < 2; j++) { c.mat[i][j] += a.mat[i][k]*b.mat[k][j]; c.mat[i][j] %= mod; } return c; } Matrix Pow( Matrix x, int n, int mod ){ Matrix c; c.unit(); while(n){ if(n&1) c = mult(c,x,mod); x = mult(x,x,mod); n >>= 1; } return c; } void init(int a,int b){ int a1 = 2*a, b1 = b-a*a; T.mat[0][0] = 0; T.mat[0][1] = 1; T.mat[1][0] = b1; T.mat[1][1] = a1; A.zero(); A.mat[0][0] = 2; A.mat[1][0] = 2*a; } int main(){ int a,b,n,m; while( scanf("%d%d%d%d",&a,&b,&n,&m) != EOF){ init(a,b); T = Pow( T, n, m ); A = mult( T, A, m ); printf("%lld\n", (A.mat[0][0]+m)%m ); } return 0; }