这道以我也是服了,折腾了一天。对我这样的新手菜鸡而言,这道题拿到就先试了一下暴力(初生牛犊不怕虎T_T),T了之后就没想到办法了,然后看了一下搜了一下思路,矩阵快速幂!!!我居然把这档子事儿给忘了,递推式,数据爆炸,太符合应用场景了,于是就开始着手往这方走,但是怎么也化不出相加 形式,上网弄了好久才明白,我还是觉得很多博客太跳了,一开始的式子我就不知道哪儿来的。不过最后还是找到了一位大佬的,然后弄懂了,这里分享一下我看懂的。
#include<iostream>
#include<algorithm>
#include<vector>
#include<time.h>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<functional>
#include<map>
#include<queue>
#define mod (1000000000+7)
#define maxn 10000000+5
#define SIZE 200000+10
typedef long long ll;
const int inf_max = 0x3f3f3f3f;
const int inf_min = 0xc0c0c0c0;
using namespace std;
ll n,a,b,c,p,l,ny_c; //l表示从左到i个位置出现了几个左括号,r表示从右边到位置i有几个右括号
struct Mat
{
ll mat[3][3];
}e,start,t;
ll Fast_power(ll base,ll power,ll m) //正确
{
base%=m;
ll res=1;
while(power)
{
if(power&1)
res=res*base%m;
base=base*base%m;
power>>=1;
}
return res%m;
}
Mat Multi(Mat a, Mat b,ll m)
{
Mat c;
memset(c.mat, 0, sizeof(c.mat));
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
c.mat[i][j] = (c.mat[i][j] +a.mat[i][k] * b.mat[k][j])%(m-1);
return c;
}
Mat Mat_fpower(Mat base,ll power,ll m) //正确
{
Mat res=e;
while(power)
{
if(power&1)
res=Multi(res,base,m);
base=Multi(base,base,m);
power>>=1;
}
return res;
}
void Initial(ll a,ll b,ll c,ll m)
{
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
if(i==j)
e.mat[i][j]=1;
}
start.mat[0][1]=1;start.mat[0][0]=c%m;start.mat[1][0]=1;
start.mat[2][2]=1;start.mat[2][0]=1;
t.mat[0][0]=b%m,t.mat[0][2]=b%m;
}
void Input()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
t.mat[i][j]=0;
start.mat[i][j]=0;
e.mat[i][j]=0;
}
scanf("%I64d%I64d%I64d%I64d%I64d",&n,&a,&b,&c,&p);
if(n==1)
{
printf("1\n");
}
else if(n==2)
{
printf("%I64d\n",Fast_power(a,b,p));
}
else
{
Initial(a,b,c,p);
Mat tmp=Mat_fpower(start,n-2,p);
Mat ans=Multi(t,tmp,p);
ll t1=ans.mat[0][0];
if(a%p)
{
t1%=(p-1);
printf("%I64d\n",Fast_power(a,t1,p));
}
else
{
if(t1<(p-1))
printf("%I64d\n",Fast_power(a,t1,p));
else
{
t1=t1%(p-1)+p-1;
printf("%I64d\n",Fast_power(a,t1,p));
}
}
}
}
}
int main()
{
Input();
return 0;
}
总结一下出现的问题吧,首先就是矩阵快速幂的时候%(p-1),一开始根本没注意到这个问题,以为只有最后把kn求出来后才需要模(p-1),结果在矩阵乘法的时候就要%(p-1)了;再者就是对于对于运算结果的取余问题,该取余的地方一定要取,否则连错在哪儿都难找(前天ans忘了取余debug了一上午T_T).数论对我有点儿不太友好,能过得基本一趟,不能过的至少debug半天,果然还是我太菜了吧.