题目大意:求 ⌈(a+b√)n⌉modm ,其中有 (a−1)2<b<a2
怎么感觉和 JLOI2015 的那道题差不多QAQ
由条件得
0<a−b√<1
先看
(a+b√)n+(a−b√)n
展开一下就知道它一定是个整数嘛
所以原式
Sn=⌈(a+b√)n+(a−b√)n⌉modm
然后就可以得到递推式
Sn=2aSn−1+(b−a2)Fn−2
矩乘,没了…QAQ
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<string>
#include<cstring>
#define LL long long
using namespace std;
LL n,m,a,b;
LL A[2][2],t[2][2],ret[2][2];
void mul(LL A[][2],LL B[][2])
{
for (int i = 0;i < 2;i ++)
for (int j = 0;j < 2;j ++)
{
t[i][j] = 0;
for (int k = 0;k < 2;k ++)
(t[i][j] += A[i][k] * B[k][j]) %= m;
}
for (int i = 0;i < 2;i ++)
for (int j = 0;j < 2;j ++)
A[i][j] = t[i][j];
}
void ksm(int B)
{
ret[0][0] = ret[1][1] = A[1][0] = 1;
ret[0][1] = ret[1][0] = A[1][1] = 0;
A[0][0] = a * 2,A[0][1] = b - a * a;
for (;B;B >>= 1,mul(A,A))
if (B & 1) mul(ret,A);
}
LL F(int n)
{
int s = sqrt(b),t = (s * s != b);
if (n == 1) return (a + s + t) % m;
else return (a * a + b + (int)(sqrt(b) * a * 2) + t) % m;
}
int main()
{
while (~scanf("%lld%lld%lld%lld",&a,&b,&n,&m))
{
if (n == 1)
{
cout << F(1) << endl;
continue;
}
ksm(n - 2);
cout << ((ret[0][0] * F(2) + ret[0][1] * F(1)) % m + m) % m << endl;
}
return 0;
}