关于欧拉工程的一道递推题
今天来讲的是在欧拉工程上的一道递推题,题目描述如下链接。
题目:https://projecteuler.net/problem=492
当然,这道题在51Nod上有一个比较通用的版本,链接如下
题目:http://www.51nod.com/contest/problem.html#!problemId=1361
题意:给定,并且有,给定两个数和,求的值。其中
满足和,并且为素数。
分析:首先对原递推式进行变换得到
那么令,继而有,而。到了这里,假设
那么我们带入继续递推会发现一个神奇的结论
其中假设取其中一个解如下
那么得到如下
好了,到了这里,最直观的做法就是根据上述公式求出,然后会带回去求出即可。
如果想用二次剩余的方法来做,因为可能无解,所以不能用这种方法做。看成更一般
形式的求解,比如下面
那么回忆之前的一篇文章:http://blog.csdn.net/acdreamers/article/details/8994222,重
点是HDU4565题,这是明显可以构造矩阵的,具体如何构造不再赘述。然后先得到递推式如下
所以最终得到如下
可以看到矩阵的指数很大,所以需要降小,而这是一个经典的矩阵找寻环节问题。之前有篇文章,如下
链接:http://blog.csdn.net/acdreamers/article/details/25616461
当时那道题由于要求最小的循环节,所以要求比较精确,必须枚举因子。但是对于本题不同,我们只要能
求出一个合理的循环节即可,不要求最小的,因为不影响最终结果。
参照当时的结论,由于117不是素数,所以只有两种情况。
(1)如果117是的二次剩余时,最小循环节是的因子,我们可以取作为循环节。
(2)如果117是的二次非剩余时,最小循环节是的因子,可以取作
为循环节。
到了这里大部分问题都已经解决。实际上当117是的二次非剩余时,循环节可以为,至于为什么是
正确的,请来个大神证明! 另外为2或者3时,需要特判。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>using namespace std;
typedef long long LL;const int N = 2;struct Matrix
{LL m[N][N];
};Matrix I =
{1, 0,0, 1
};LL quick_mod(LL a, LL b, LL m)
{LL ans = 1;a %= m;while(b){if(b & 1){ans = ans * a % m;b--;}b >>= 1;a = a * a % m;}return ans;
}LL Legendre(LL a, LL p)
{ LL t = quick_mod(a, (p - 1) >> 1, p); if(t == 1) return 1; return -1;
} Matrix multi(Matrix a, Matrix b, LL m)
{Matrix c;for(int i = 0; i < N; i++){for(int j = 0; j < N; j++){c.m[i][j] = 0;for(int k = 0; k < N; k++)c.m[i][j] += a.m[i][k] * b.m[k][j] % m;c.m[i][j] %= m;}}return c;
}Matrix power(Matrix A, LL k, LL m)
{Matrix ans = I, p = A;while(k){if(k & 1){ans = multi(ans, p, m);k--;}k >>= 1;p = multi(p, p, m);}return ans;
}LL GetLoop(LL p)
{if(Legendre(117, p) == -1)return p + 1;return p - 1;
}int main()
{int T;scanf("%d", &T);while(T--){LL n, p;scanf("%lld %lld", &n, &p);if(p == 2 || p == 3){puts("1");continue;}Matrix A;A.m[0][0] = 11 % p;A.m[0][1] = p - 1;A.m[1][0] = 1;A.m[1][1] = 0;LL loop = GetLoop(p);LL x = quick_mod(2, n - 1, loop);x = ((x - 1) % loop + loop) % loop;Matrix ans = power(A, x, p);LL res = (ans.m[1][0] * 119 % p + ans.m[1][1] * 11 % p) % p;res = ((res - 5) % p + p) % p;res = res * quick_mod(6, p - 2, p) % p;printf("%lld\n", res);}return 0;
}
关于欧拉工程的一道递推题相关推荐
- HDU - 2044一只小蜜蜂 一道递推题
一只小蜜蜂 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> ...
- 停不下来的团长奥尔加(一道递推题,思维很好啊....)
停不下来的团长奥尔加 [题目描述] 奥尔加在一个长度为n+1的街道上跑着,初始,奥尔加在位置1上,他想要跑到 位置n+1去保护团员ride on. 空旷的大路上难免会有暗杀者,当奥尔加走到位置i时,会 ...
- 欧拉工程第12题 第一个拥有超过500个约数的三角形数是多少
题目 三角形数序列是由对自然数的连加构造而成的.所以第七个三角形数是1+2+3+4+5+6+7=281+2+3+4+5+6+7=28. 那么三角形数序列中的前十个是: 1,3,6,10,15,21,2 ...
- 欧拉函数的一道练习题(附加容斥做法)
jzd同学今天告诉了我们一道关于欧拉函数的题,一开始觉得毫无头绪,当身旁的erge同学切完开始装(xiao)逼(zhang)的时候,他无意间透露的欧拉函数四个字启发了我,最近做了一道很相似的题HDU1 ...
- gcd + 扩展欧几里得定理+递推乘法逆元(模板)
gcd: int gcd(int a, int b){ return b==0? a: gcd(b, a%b); } 扩张欧几里得定理: 扩展欧几里德算法是用来在已知a, b求解一组x,y使得ax+b ...
- 斐波拉契数列的递推递归求解算法
介绍: 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数 ...
- 斐波拉契数列C++--递推
[问题描述] 有斐波拉契数列1,1,2,3,5,8,13--,请按每行m个数据输出该裴波拉契数列的前n项,其中m,n从键盘输入 [输入形式] m为1-7之间的整数,n值是1-50之间的任意一整数. [ ...
- 欧拉工程第57题:Square root convergents
题目链接 Java程序 package projecteuler51to60;import java.math.BigInteger; import java.util.Iterator; impor ...
- 我的欧拉工程之路_3
Largest prime factor Problem 3 The prime factors of 13195 are 5, 7, 13 and 29. What is the largest p ...
最新文章
- java中xxe漏洞修复方法
- task一个任务结束后执行另一个操作
- c语言操作目录,c语言文件操作整理
- 使用的 SQL Server 版本不支持数据类型“datetime2”解决办法
- SAPGUI里实现自定义的语法检查
- linux禁止root用户直接登录sshd并修改默认端口
- c语言限制字符数,C语言中“不受限制”的字符串函数总结.pdf
- ECCV 2020 | 超快的车道线检测
- Kafka常用命令之kafka-console-consumer.sh
- java 解析数据包_一种基于Java语言的网络通讯数据包解析方法与流程
- python智能化推荐_windows python flask
- Android之Input子系统事件分发流程
- 20200210_logistic回归来预测违约的概率
- 测试工程师必备Linux知识点
- 在Windows系统上安装zookeeper
- CTF之Bugku 秋名山老司机
- android好用拍照框架,Github挺好用的android图片选择框架(拍照+从相册)
- 访问对象存储资源下载变成预览
- Windows10打开“运行”窗口
- JavaScript实现注册页面的表单验证