您的位置:首页 > 其它

HZAU 1202 GCD (矩阵快速幂 + GCD)

2017-04-23 19:58 483 查看

Problem Description

Xiao Ming found the compute time of gcd(fibn,fibn+1) is the most when he learnt the gcd, and the result of it is always fib1 but he is not satisfied with the simple compute result.

He wants to know what gcd(1+Sn,1+Sm) equals.

And gcd is greatest common divisor,

fib1=1,fib2=1,fibn=fibn−1+fibn−2(n≥3)

Sn=∑i=1nfibi

Input Description

The first line is an positive integer T. (1 ≤ T ≤ 10^3) indicates the number of test cases. In the next T lines, there are three positive integer n, m, p(1 ≤ n, m, p ≤ 10^9) at each line.

Output Description

In each test case, output the compute result of gcd(1+Sn,1+Sm)%p at one line.

Sample Input:

1
1 2 3


Sample Output:

1


题意

给出 n,m,p 三个整数,求斐波那契数列前 n 项和与前 m 项和的最大公约数模 p 。

思路

斐波那契数列有这样两条性质:

gcd(Fn,Fm)=Fgcd(n,m)

F1+F2+F3+F4+F5+...+Fn+1=Fn+2

于是,题目的答案便是 Fgcd(n,m)%p 咯!

最大公约数可以用辗转相除法求得,然后再利用矩阵快速幂得到斐波那契数第 k 项,记得模 p 哦~

AC 代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
typedef long long LL;

LL n,m,mod;
LL gcd(LL a,LL b)
{
if(b==0)return a;
return gcd(b,a%b);
}

struct node
{
LL mp[2][2];
void init(LL a,LL b,LL c,LL d)
{
mp[0][0]=a;
mp[0][1]=b;
mp[1][0]=c;
mp[1][1]=d;
}
void mult(node x,node y)                //两矩阵乘法
{
memset(mp,0,sizeof(mp));
for(LL i=0; i<2; i++)
for(LL j=0; j<2; j++)
for(LL k=0; k<2; k++)
mp[i][j]=(mp[i][j]+x.mp[i][k]*y.mp[k][j])%mod;
};
} init;

struct node expo(struct node x, LL k)  //进行k次幂运算
{
struct node tmp;
tmp.init(1,0,0,1);                      //单位矩阵
while(k)                                //快速幂部分
{
if(k&1)tmp.mult(tmp,x);
x.mult(x,x);
k>>=1;
}
return tmp;
}

int main()
{
int T;
ios::sync_with_stdio(false);
cin>>T;
while(T--)
{
cin>>n>>m>>mod;
int k=gcd(n+2,m+2);
init.init(1,1,1,0);
cout<<expo(init,k).mp[0][1]%mod<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: