【HDU4565】So Easy!

【HDU4565】So Easy!

题面

要你求

\[\lceil (a+\sqrt b)^n \rceil \% m \]

其中\(0<a,m<2^{15},(a-1)^2<b<a^2,0<b,n<2^{31}\)

题解

这个向上取整放在这里很丑对吧,我们化一下柿子。

\[\because (a-1)^2<b<a^2\\ \therefore a-\sqrt b \]

因为\((a-\sqrt b)^n\)是个很小的小数且\(a-\sqrt b\)\(a+\sqrt b\)共轭,所以

\[(a-\sqrt b)^n+(a+\sqrt b)^n=\lceil (a+\sqrt b)^n \rceil \]

\(C_n=(a-\sqrt b)^n+(a+\sqrt b)^n\)

\[C_n*\left((a-\sqrt b)+(a+\sqrt b)\right) \\ = (a+\sqrt b)^{n+1}+(a-\sqrt b)^{n+1}+(a^2-b)*(a-\sqrt b)^{n-1}+(a^2-b)*(a+\sqrt b)^{n-1}\\ = C_{n+1}+(a^2-b)C_{n-1}\\ \Leftrightarrow C_{n+1}=2a*C_n+(b-a^2)C_{n-1} \]

然后构一个矩阵,就可以快速幂了:

\[ \left[ \begin{matrix} 2a & b-a^2\\ 1 & 0\\ \end{matrix} \right] * \left[ \begin{matrix} C_{n} \\ C_{n-1} \\ \end{matrix} \right] = \left[ \begin{matrix} C_{n+1} \\ C_n \\ \end{matrix} \right] \]

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm> 
using namespace std; 
typedef long long ll; 
ll A, B, N, Mod; 
struct Matrix { 
	ll m[2][2]; 
	void clear() { memset(m, 0, sizeof(m)); } 
	void init() { for (int i = 0; i < 2; i++) m[i][i] = 1; } 
	ll *operator [] (int id) { return m[id]; } 
	Matrix operator * (const Matrix &b) { 
		Matrix res; res.clear(); 
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 2; j++)
				for (int k = 0; k < 2; k++) 
					res[i][j] = (res[i][j] + m[i][k] * b.m[k][j] % Mod) % Mod; 
		return res; 
	} 
} S, T; 
int main () { 
	while (~scanf("%lld%lld%lld%lld", &A, &B, &N, &Mod)) { 
		S.clear(), T.clear(); 
		S[0][0] = (A * 2) % Mod, S[1][0] = 2; 
		T[0][0] = (A * 2) % Mod, T[0][1] = ((B - A * A % Mod) % Mod + Mod) % Mod; 
		T[1][0] = 1, T[1][1] = 0;
		Matrix res; res.clear(); res.init(); 
		while (N) { if (N & 1) res = res * T; N >>= 1; T = T * T; } 
		S = res * S; 
		printf("%lld\n", (S[1][0] % Mod + Mod) % Mod); 
	} 
	return 0; 
} 
posted @ 2019-01-21 10:26  heyujun  阅读(176)  评论(0编辑  收藏  举报