SO EASY 不是说题目 so easy,是说题目名字叫 so easy。。。。。
这个题可以这样想:直接用 double 求结果肯定是不行的(精度不够啥的),因为题目要求的是整数部分,可以考虑把有理数拆一下
设 (a+sqrt(b))^ n = Xn + Yn*sqrt(b) , 那么 (a + sqrt(b) )^ (n+1) = Xn*a+Yn*b+ ( Xn + Yn*a )*sqrt(b)
又 (a-1)^2<b<a^2 , 所以有 0 < ( a-sqrt(b) ) ^ n < 1 。
又因为 ( a+sqrt(b) ) ^ n + ( a-sqrt(b) ) ^ n = Xn + Yn*sqrt(b) + Xn - Yn*sqrt(b) = 2*Xn , 所以 ( a+sqrt(b) ) ^ n = 2*Xn - C (C小于1大于0)
然后得 ( a+sqrt(b) ) ^ n 向上取整后为 2*Xn
(最终还是翻看了网上的大佬得知为什么结果是 2*Xn 。。。。。。)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <map>
#include <math.h>
using namespace std;
typedef __int64 LL;
const LL MAXN=333;
LL a,b,n,m,x,y;
struct rec
{
LL a11,a12,a21,a22;
rec(){}
rec (LL a1,LL a2,LL a3,LL a4){a11=a1;a12=a2;a21=a3;a22=a4;}
rec operator*(rec p)
{
return rec(a11*p.a11+a12*p.a21,a11*p.a12+a12*p.a22,a21*p.a11+a22*p.a21,a21*p.a12+a22*p.a22);
}
rec operator%(LL p)
{
return rec(a11%p,a12%p,a21%p,a22%p);
}
}r,ans;
void fast(LL n,LL m)
{
while(n)
{
if(n&1)
{
ans=ans*r;
}
r=r*r;
r=r%m;
ans=ans%m;
n/=2;
}
}
int main()
{
while(scanf("%I64d%I64d%I64d%lld",&a,&b,&n,&m)!=-1)
{
r.a11=a,r.a12=b,r.a21=1,r.a22=a;
ans.a11=1,ans.a12=0,ans.a21=0,ans.a22=1;
fast(n,m);
x=ans.a11*2;
x=(x%m+m)%m;
printf("%I64d\n",x);
}
return 0;
}
本人蒟蒻,如有错误,还望指正