【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;
}