求$G(a,b,n,p) = (a^{\frac {p-1}{2}}+1)(b^{\frac{p-1}{2}}+1)[(\sqrt{a} + \sqrt{b})^{2F_n} + (\sqrt{a} - \sqrt{b})^{2F_n}] (mod p)$

左边可以看出是欧拉判定准则,那么只有当a,b其中一个满足是模p下的非二次剩余时G()为0。

右边的式子可以先把平方放进去,发现这个已经是通项公式了,那么$a+b+\sqrt{ab}$和$a+b-\sqrt{ab}$就是它的特征根了,反代回二阶特征方程,得到递推式的两个系数$2(a+b)$,$-(a-b)^2$,然后可以使用矩阵快速幂了,注意其项数是$F(n)$,指数循环节,欧拉降幂,其矩阵快速幂的过程中模p-1就行了。

/** @Date    : 2017-10-11 22:30:33
* @FileName: HDU 3802 斐波那契特征方程解递推式 矩阵快速幂.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std; const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8; LL mod; LL fpow(LL a, LL n)
{
LL res = 1LL;
while(n)
{
if(n & 1LL) res = (res * a % mod + mod) % mod;
a = (a * a % mod + mod) % mod;
n >>= 1LL;
}
return res;
} struct matrix
{
LL mat[2][2];
matrix(){MMF(mat);}
void id(){
mat[0][0] = mat[1][1] = 1LL;
}
matrix operator *(const matrix &b){
matrix c;
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
for(int k = 0; k < 2; k++)
{
c.mat[i][j] = (c.mat[i][j] + mat[i][k] * b.mat[k][j] % mod) % mod;
}
return c;
}
matrix operator ^(LL n){
matrix res;
matrix a = *this;
res.id();
while(n)
{
if(n & 1LL)
res = res * a;
a = a * a;
n >>= 1LL;
}
return res;
}
}; LL fib(LL n)
{
mod--;
matrix T;
T.mat[0][0] = 1LL, T.mat[0][1] = 1LL;
T.mat[1][0] = 1LL, T.mat[1][1] = 0LL;
matrix tmp = (T^(n-1));
LL ans = ((tmp.mat[0][0] + tmp.mat[1][0])%mod + mod) % mod;
mod++;
return ans;
} LL fun(LL a, LL b, LL n)
{
LL ans = (fpow(a, (mod - 1)>>1) + 1LL) * (fpow(b, (mod-1)>>1) + 1LL) % mod;//注意这里也要取模...
if(ans == 0)
return 0;
if(n < 2)
return (a + b) * 2LL % mod * ans % mod;
LL e = fib(n);
//cout << e << endl;
if(e == 0)
e = mod - 1;
matrix A;
A.mat[0][0] = (a + b) * 2LL % mod, A.mat[0][1] = 1LL;
A.mat[1][0] = (b - a) * (a - b) % mod, A.mat[1][1] = 0LL;
A = A^(e - 1);
ans = (ans * ((a + b) * 2LL % mod * A.mat[0][0] + A.mat[1][0] * 2LL % mod) % mod) % mod;
while(ans < 0)
ans += mod;
return ans;
}
int main()
{
int T;
cin >> T;
while(T--)
{
LL a, b, n;
scanf("%lld%lld%lld%lld", &a, &b, &n, &mod);
LL ans = fun(a, b, n);
printf("%lld\n", ans);
}
return 0;
}

最新文章

  1. 关于c++的 vector 容器的使用及创建方法
  2. Entity Framework 中的Code First 中引入数据库函数
  3. DataReader用法
  4. C#中的接口
  5. NGUI Atlas
  6. loading等待载入正在加载的动画GIF图片圆形图标
  7. Zabbix源码包安装
  8. group by 获取总记录数
  9. javaSE第七天
  10. 《Genesis-3D开源游戏引擎完整实例教程-2D射击游戏篇:简介及目录》(附上完整工程文件)
  11. 验证码计时 -- UIButton setTitle 闪烁问题解决方案
  12. 小米2s刷机
  13. JavaBean规范
  14. apache+php+mysql运行环境
  15. 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
  16. c++消息队列的实现
  17. Docker学习之2——镜像
  18. linux affinity
  19. C#中字符串转换为计算公式(自定义公式的计算)
  20. [Leetcode 122]买股票II Best Time to Buy and Sell Stock II

热门文章

  1. MAVEN教程--01安装|创建|解释
  2. 团队作业4——第一次项目冲刺(Alpha版本)2017.11.18
  3. 封装GetQueryString()方法来获取URL的value值(转载)
  4. Robot Framework 教程 (7) - 使用For循环
  5. .NET Socket 简单入门
  6. javascript 进阶篇1 正则表达式,cookie管理,userData
  7. HDU 6166 Senior Pan(二进制分组+最短路)
  8. InvalidArgumentError: You must feed a value for placeholder tensor &#39;Placeholder_1&#39; with dtype float and shape [?,10]
  9. BZOJ3481 DZY Loves Math III(数论+Pollard_Rho)
  10. Spanning Tree Protocol (STP) in NetScaler Appliance