hdu1588

来源:互联网 发布:视频音轨分离软件 编辑:程序博客网 时间:2024/06/04 18:12

以后遇到这种数据接近 limit 的必须小心  乘法!

要不就全用long long   __int64

推倒~


g(i)=k*i+b;代入Si  得

sn=f(b)+f(k+b)+f(2*k+b)+...+f((n-1)k+b)


建立斐波那契的递推的矩阵 A

sn=A^b * (I+A^K+...+A^((n-1)*K))  * (f[0]#f[1])

(I为单位矩阵)


设 R 为A^K

构造矩阵


代入  ..AC



#include <stdio.h>#include <string.h>#define ff(i,n) for(int i=0;i<n;i++)int M;struct Mat{    int m[2][2];    friend Mat operator*(Mat a,Mat b)    {        Mat c;        memset(c.m,0,sizeof(c.m));        ff(i,2)        ff(j,2)        ff(k,2)        {            c.m[i][j]+=((<span style="color:#FF0000;">long long</span>)(a.m[i][k]%M)*(b.m[k][j]%M))%M;///care            c.m[i][j]%=M;        }        return c;    }    friend Mat operator+(Mat a,Mat b)    {        ff(i,2)        ff(j,2)        {            a.m[i][j]+=b.m[i][j]%M;            a.m[i][j]%=M;        }        return a;    }}I,R,A;void DEBUG(Mat a){    ff(i,2)    {        ff(j,2)            printf("%d\t",a.m[i][j]);        puts("");    }    puts("");}struct SMat{    Mat m[2][2];    friend SMat operator*(SMat a,SMat b)    {        SMat c;        memset(c.m,0,sizeof(c.m));        ff(i,2)        ff(j,2)        ff(k,2)            c.m[i][j]=c.m[i][j]+a.m[i][k]*b.m[k][j];        return c;    }}W;Mat Power(Mat a,int n){    Mat c;    memset(c.m,0,sizeof(c.m));    ff(i,2)        c.m[i][i]=1;    for(;n;n>>=1)    {        if(n&1)            c=c*a;        a=a*a;    }    return c;}SMat SPower(SMat a,int n){    SMat c;    memset(c.m,0,sizeof(c.m));    ff(i,2)        c.m[i][i]=I;    for(;n;n>>=1)    {        if(n&1)            c=c*a;        a=a*a;    }    return c;}int main(){    //freopen("hdu1588in","r",stdin);    memset(I.m,0,sizeof(I.m));    memset(A.m,0,sizeof(A.m));    memset(W.m,0,sizeof(W.m));    I.m[0][0]=I.m[1][1]=A.m[0][1]=A.m[1][0]=A.m[1][1]=1;    int k,b,n;    while(scanf("%d%d%d%d",&k,&b,&n,&M)!=EOF)    {        W.m[0][1]=W.m[1][1]=I;        R=Power(A,k);        Mat a=Power(A,b);        SMat w=W;        w.m[0][0]=R;        w=SPower(w,n);        a=a*w.m[0][1];        //DEBUG(I);        printf("%d\n",a.m[0][1]%M);    }    return 0;}


0 0
原创粉丝点击