给你一个式子
发现n十分的大 1018 ,又只给1000ms,只能用 O(logn) 的方法
有什么可以做呢?
很明显是矩阵乘法!!!
先要弄初始矩阵。
先设初始矩阵有一位 Xn ,首先需要乘,并不用多开一位。要从 Xn−1 推过来,多开一位 Xn−1 。然后还要加c,再多开一位c。
那么初始矩阵有3位,[ Xn−1 ][ Xn ][ c ]
那么很明显要从 Xn 推到 Xn+1 ,那么很明显转移矩阵
{{0,0,0},
{1,a,0},
{0,1,1}
}
可以用快速乘,类似快速幂,速度比快速幂多一个log
比如说是a*b,我们设f(i)=a*i
那么把b拆一下,f(b)=f(b/2) * 2+a *(b mod 2)
ll qsc(ll x,ll y){
ll z=0;
if(y==0)return z;
z=qsc(x,y/2);
z=z*2%m;
if(y%2==1)z=(z+x)%m;
return z;
}
其实还可以用黑科技
把这些数强制转成double再转回来
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define ll long long
using namespace std;
ll i,j,k,l,t,n,m,ans,a,b,c,g,x0,x1;
ll qsc(ll x,ll y){
ll z=0;
if(y==0)return z;
z=qsc(x,y/2);
z=z*2%m;
if(y%2==1)z=(z+x)%m;
return z;
}
struct node{
ll ju[3][3];
node friend operator *(node a,node b){
node c;
memset(c.ju,0,sizeof(c.ju));
fo(i,0,2){
fo(j,0,2){
fo(k,0,2){
c.ju[i][j]=(c.ju[i][j]+qsc(a.ju[i][k],b.ju[k][j]))%m;
}
}
}
return c;
}
}f,ber;
void qsm(node x,ll y){
while(y!=0){
if(y&1==1)f=f*x;
x=x*x;
y=y/2;
}
}
int main(){
scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x0,&n,&g);
ber.ju[0][0]=0;ber.ju[0][1]=0;ber.ju[0][2]=0;
ber.ju[1][0]=1;ber.ju[1][1]=a;ber.ju[1][2]=0;
ber.ju[2][0]=0;ber.ju[2][1]=1;ber.ju[2][2]=1;
x1=(qsc(a,x0)+c)%m;
f.ju[0][0]=x0,f.ju[0][1]=x1,f.ju[0][2]=c;
qsm(ber,n-1);
printf("%lld",f.ju[0][1]%g);
}