有一个序列是这样定义的:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
给出A,B和N,求f(n)的值。
Input
输入3个数:A,B,N。数字之间用空格分割。(-10000 <= A, B <= 10000, 1 <= N <= 10^9)
Output
输出f(n)的值。
Input示例
3 -1 5
Output示例
6
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL long long
using namespace std;
const int MAXN =100+10;
const LL mod=7;
struct Matrix{
LL a[MAXN][MAXN];
int r,c;
};
Matrix ori,res;
LL a,b,n;
void init(){
memset(res.a,0,sizeof(res.a));
res.r=2;res.c=2;
for(int i=1;i<=2;i++) //将结果矩阵赋值为单位矩阵
res.a[i][i]=1;//单位矩阵A就是 [未知矩阵]B*A=B;
ori.r=ori.c=2;
ori.a[1][1]=a; ori.a[1][2]=b; ori.a[2][1]=1;// 初始化过度矩阵
ori.a[2][2]=0;
}
Matrix multi(Matrix x,Matrix y){
Matrix z;
memset(z.a,0,sizeof(z.a));
z.r=x.r; z.c=y.c;
for(int i=1;i<=x.r;i++){
for(int k=1;k<=x.c;k++){
if(x.a[i][k]==0) continue;//小优化
for(int j=1;j<=y.c;j++)
z.a[i][j]=(z.a[i][j]+(x.a[i][k]*y.a[k][j]%mod))%mod;
}
}
return z;
}
void Matrix_mod(int n){
while(n){
if(n&1) res=multi(ori,res);
ori=multi(ori,ori);
n>>=1;
}
Matrix it;it.r=2;it.c=1; // 初始矩阵
it.a[1][1]=1; it.a[2][1]=1;
res=multi(res,it); // 初始矩阵*过渡矩阵的幂 就是结果
printf("%lld\n",(res.a[2][1]%mod+mod)%mod);// 因为有可能是负数,所以这样处理
}
int main(){
scanf("%lld%lld%lld",&a,&b,&n);
init();
Matrix_mod(n-1); // 根据构造可知 n-1的幂才是f[n] ;
return 0;
}
根据鸽巢原理,循环节最大就是49. 。
所以我们知道这个是有规律的,我们可以找到其循环节然后来处理。
还有就是负数的情况不能够考虑,所以就有了(()%7+7)%7的操作。
代码
#include <cstdio>
int f[60];
int main(){
int a,b,n;
scanf("%d%d%d",&a,&b,&n);
f[1] = f[2] = 1;
for (int i = 3;i <= 50; ++i){
f[i] = (a*f[i-1]+b*f[i-2])%7+7;
f[i]%=7;
}
int f1,f2,flag = 0;
for (int i = 1; i < 50; ++i){// 枚举找到循环节
for (int j = i+1;j<=50; ++j){
if (f[j]==f[i]&&f[j+1]==f[i+1]){
f1 = i;
f2 = j;
flag = 1;
break;
}
}
if (flag) break;
}
if (n<f1){
printf("%d\n",f[n]);
}else printf("%d\n",f[f1+(n-f1)%(f2-f1)]);
return 0;
}