题干:
给你三个数a,b,c,求 F[
a
b
a^b
ab]%c的值,F[i]表示第i个斐波那契数。
其中0<a,b<
2
64
2^{64}
264
思路:
2
64
2^{64}
264有20位,需要用unsigned long long来存储,用cin和cout来输出输出。
我们先来写一下斐波那契数列的前十位
1 1 2 3 5 8 13 21 34 55
1 1 0 1 1 0 1 1 0 1(c=2的时候3个一次循环(1 1 0))
1 1 2 0 2 2 1 0 1 1(c=3的时候8个一次循环(1 1 2 0 2 2 1 0))
一个数模n的余数最多有n种,所以最多有
n
2
n^2
n2项重复出现,所以对F[0]~F[
n
2
n^2
n2]进行暴力,找到开始循环的地方,然后记录下来,就可以将
a
b
a^b
ab缩小了。
设周期位M,则F[
a
b
a^b
ab]%c == F[
x
b
x^{b}
xb%M] (x=a%M).
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <math.h>
using namespace std;
typedef unsigned long long ll;
int f[1200][6200],F[6200];
ll qc(ll a,ll b,int c)
{
ll ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%c;
a=(a*a)%c;
b>>=1;
}
return ans%c;
}
int main()
{
int t,c;
for(int i=2;i<=1100;i++){
f[i][0]=f[i][1]=1;
for(int j=2;;j++){
f[i][j]=(f[i][j-1]+f[i][j-2])%i;
if(f[i][j]==1&&f[i][j-1]==1){
F[i]=j-1;
break;
}
}
}
scanf("%d",&t);
while(t--)
{
ll a,b;
cin>>a>>b>>c;
if(c==1)
{
printf("0\n");
continue;
}
cout<<f[c][qc(a%F[c],b,F[c])-1]<<endl;
}
return 0;
}