GCD

问题 : GCD

时间限制: 1 Sec   内存限制: 1280 MB
提交: 18   解决: 7
[ 提交][ 状态]

题目描述

输入

 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.

输出

样例输入

1 
1 2 3

样例输出

1

题目大意:给出一个公式,现在要求求出公式的最后结果。

解题思路: 题目上可以看到数据范围很大,用普通方法肯定不行,对于这种情况应该只有两种情况,一种是式子结果在数据范围内很少,那么这时间可以直接打表,如果特别多,那么就表示这种题有某种规律,可以先试着写出普通的代码,输出一些数据查找规律。这一题正好是后一种情况,对于盖提而言式子的结果是求出第m,n最大公约数加上二个斐波那契额数字。当然这样来说数据范围同样很大,因此应该鞥想到矩阵快速幂来求解。

快速幂还是很好理解的,对于a^b 

当b为偶数时可以转化为a^2的b/2

当b为奇数时可以转化为a^2的b/2次方乘以a

而对于矩阵快数幂又涉及到了矩阵相乘,再加上快速幂来迅速解决问题。

对于矩阵乘法求斐波那契额数可以搜索资料了解, 就不在多说了

代码:

#include<stdio.h>

#include<string.h>

#define N 10
long long p;
typedef struct stu{
long long a[4][4];
}st;
st fun(st u,st v)
{
long long i,j,k;
long long c[N][N]={0};
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++)
{
  c[i][j]=(c[i][j]+u.a[i][k]*v.a[k][j])%p;
}
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
  u.a[i][j]=c[i][j];
return u;
}
st pow(long long n)
{
    st u,v;
    u.a[1][1]=u.a[1][2]=u.a[2][1]=1;
v.a[1][1]=1;v.a[2][2]=1;
u.a[2][2]=v.a[1][2]=v.a[2][1]=0;
    while(n)
{
  if(n&1)
   v=fun(u,v);
  u=fun(u,u);
  n=n>>1;
}
    return v;
}
long long fun1(long long a,long long b)
{
if(!b)
return a;
else
return fun1(b,a%b);
}
int main()
{
long long i,j,k,m,n,x,y,t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&m,&n,&p);
st w,z,u1,v1;
m+=2;n+=2; 
m=fun1(m,n);
u1=pow(m);
x=u1.a[1][2];
printf("%lld\n",x%p);
}
return 0;

}

本人菜鸟一个,如若文章能给你有所启发不胜荣幸。如有不足之处还望指出,非常感谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值