HDU 4565 So Easy ***MATH

来源:互联网 发布:mac 显示隐藏文件夹 编辑:程序博客网 时间:2024/06/03 18:33

快速幂运算:http://blog.sina().com.cn/s/blog_5cf6cbf80100qak0.html

题解写的很好:http://blog.csdn.net/crazy______/article/details/9021169

Cn=An+Bn=(a+根号b)^n+(a-根号b)^n

Bn<1

Cn=An向上取整

原式Sn=Cn%m

令Cn*((a+根号b)+(a-根号b))=Cn+1 +(a^2-b)Cn-1

得到递推

Cn+1=2a*Cn -(a^2-b)Cn-1

然后化成矩阵,用矩阵的快速幂运算


PS:非常神奇的是,这里把通项变成递推才能做,否则,循环21亿次,还真没时间

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <math.h>#include <algorithm>#define SCAND(x) scanf("%d",&(x));#define SCANS(x) scanf("%s",(x));#define PRINTD(x) printf("%d",(x));using namespace std;long long a,b,n,m;const int INF=1<<30;long long s[5];long long ans[5]={0,1,0,0,1};void getFirst(){    s[1]=2*a;    s[2]=b-a*a;    s[3]=1;    s[4]=0;    ans[1]=1;    ans[2]=0;    ans[3]=0;    ans[4]=1;}void squareIt(){    long long tmp[5];    for(int i=1;i<5;i++)    {        tmp[i]=s[i];    }    s[1]=(tmp[1]*tmp[1]+tmp[2]*tmp[3])%m;    s[2]=(tmp[1]*tmp[2]+tmp[2]*tmp[4])%m;    s[3]=(tmp[3]*tmp[1]+tmp[4]*tmp[3])%m;    s[4]=(tmp[3]*tmp[2]+tmp[4]*tmp[4])%m;}void squareSum(){    long long tmp[5];    for(int i=1;i<5;i++)    {        tmp[i]=ans[i];    }    ans[1]=(tmp[1]*s[1]+tmp[2]*s[3])%m;    ans[2]=(tmp[1]*s[2]+tmp[2]*s[4])%m;    ans[3]=(tmp[3]*s[1]+tmp[4]*s[3])%m;    ans[4]=(tmp[3]*s[2]+tmp[4]*s[4])%m;}int main(){    while(cin>>a>>b>>n>>m)    {        getFirst();        while(n)        {            if(n&1)            {                squareSum();                squareIt();            }            else            {                squareIt();            }            n>>=1;        }        long long res=(ans[3]*2*a%m+ans[4]*2%m)%m;        if(res<0)            res+=m;        cout<<res<<endl;    }}


0 0
原创粉丝点击