HDU 4565 so easy ! 矩阵快速幂

来源:互联网 发布:广州多迪网络靠谱吗 编辑:程序博客网 时间:2024/06/05 02:05



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;}
本人蒟蒻,如有错误,还望指正