以后遇到这种数据接近 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;
}