题意

设 $y = (5+2\sqrt 6)^{1+2^x}$,给出 $x, M$($0\leq x \leq 2^{32}, M \leq 46337$),求 $[y]\%M$.

分析

由通项推递推式??

设 $A_n = (5 + 2\sqrt 6)^n, B_n = (5 - 2\sqrt 6)^n,C_n = A_n + B_n$,

显然 $C_n$ 是整数,且 $B_n$ 是小于1的,所以答案就是 $C_n - 1$.

通过推导:

$C_n = A_n + B_n = (5+2\sqrt6)^n +  (5-2\sqrt6)^n$

$C_{n+1} = A_{n+1} + B_{n+1} = (5+2\sqrt6)(5+2\sqrt6)^n +  (5-2\sqrt6)(5-2\sqrt6)^n$

$C_{n+2} = A_{n+2} + B_{n+2} = (49+20\sqrt6)(5+2\sqrt6)^n +  (49-20\sqrt6)(5-2\sqrt6)^n$,

观察得 $C_{n+2} = 10C_{n+1} - C_n$

写成矩阵快速幂的形式,即

$$\begin{bmatrix} C_n\\  C_{n-1} \end{bmatrix} = {\begin{bmatrix} 10 & -1\\  1 & 0 \end{bmatrix}}^{n-1}\begin{bmatrix} C_1\\  C_0 \end{bmatrix}$$

幂太大,直接用快速幂肯定TLE。

我们可以找循环节,

由于模和转移矩阵是确定的,可以暴力打表找规律。

也可以用结论,因为 $M$ 为素数,存在循环节 $(M+1)(M-1)$。这不一定是最小的循环节,可以枚举其因子找到最小的循环节。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef long long ll;
  5. const int N=+;
  6. ll x0,x1,a,b,n,mod;
  7. char s[N];
  8.  
  9. const int maxn = + ; //p最为2e9,不会有两个超过1e5的质因数
  10. int prime[maxn], pcnt; //prime[i]表示第i个素数
  11. bool is_prime[maxn + ]; //is_prime[i]为true表示i是素数
  12. int sieve(int n)
  13. {
  14. int cnt = ;
  15. for (int i = ; i <= n; i++) is_prime[i] = true;
  16. is_prime[] = is_prime[] = false;
  17. for (ll i = ; i <= n; i++)
  18. {
  19. if (is_prime[i])
  20. {
  21. prime[cnt++] = i;
  22. for (ll j = i * i; j <= n; j += i) is_prime[j] = false; //i * i可能爆int
  23. }
  24. }
  25. return cnt;
  26. }
  27.  
  28. ll solve(ll x){
  29. ll ans1=,ans2=,xx=x;
  30. for(int i=;i<pcnt;i++){
  31. if(1ll*prime[i]*prime[i]>x) break;
  32. if(x%prime[i]==){
  33. ans1*=(prime[i]-)*(prime[i]+);
  34. ans2*=prime[i];
  35. while(x%prime[i]==) x/=prime[i];
  36. }
  37. }
  38. if(x>){
  39. ans1*=(x-)*(x+);
  40. ans2*=x;
  41. }
  42. return xx/ans2*ans1;
  43. }
  44. ll qmul(ll x,ll y,ll p){ //快速乘
  45. x%=p;
  46. y%=p;
  47. ll ans=;
  48. while(y){
  49. if(y&){
  50. ans+=x;
  51. if(ans>=p) ans-=p; //这样写不能有负数
  52. }
  53. x<<=;
  54. if(x>=p) x-=p;
  55. y>>=;
  56. }
  57. return ans;
  58. }
  59.  
  60. struct Mat{
  61. int r,c;
  62. ll m[][];
  63. Mat(){
  64. memset(m,,sizeof(m));
  65. }
  66. };
  67.  
  68. Mat mmul(Mat x,Mat y,ll p){
  69. Mat ans;
  70. ans.r=x.r;
  71. ans.c=y.c;
  72. for(int i=;i<x.r;i++)
  73. for(int k=;k<x.c;k++)
  74. for(int j=;j<y.c;j++){
  75. ans.m[i][j]+=qmul(x.m[i][k],y.m[k][j],p);
  76. if(ans.m[i][j]>=p) ans.m[i][j]-=p;
  77. }
  78. return ans;
  79. }
  80. Mat mpow(Mat x,ll y,ll p){
  81. Mat ans;
  82. ans.r=x.r;
  83. ans.c=x.c;
  84. for(int i=;i<ans.c;i++) ans.m[i][i]=;
  85. while(y){
  86. if(y&) ans=mmul(ans,x,p);
  87. x=mmul(x,x,p);
  88. y>>=;
  89. }
  90. return ans;
  91. }
  92. int main(){
  93. pcnt = sieve();
  94. while(scanf("%lld%lld%lld%lld",&x0,&x1,&a,&b) == ){
  95. scanf("%s%lld",s,&mod);
  96. ll lop=solve(mod); //循环节长度
  97. n=;
  98. int lens=strlen(s);
  99. for(int i=;i<lens;i++){
  100. n=qmul(n,,lop)+s[i]-'';
  101. if(n>=lop) n-=lop;
  102. }
  103. Mat A,T;
  104. A.r=; A.c=;
  105. A.m[][]=x1; A.m[][]=x0;
  106. T.r=; T.c=;
  107. T.m[][]=a; T.m[][]=b; T.m[][]=;
  108. if(n>){
  109. T=mpow(T,n-,mod);
  110. A=mmul(T,A,mod);
  111. }
  112. printf("%lld\n",A.m[][]);
  113. }
  114. return ;
  115. }

参考链接:https://www.cnblogs.com/addf/p/4834108.html

HDU 5451——递推式&&循环节的更多相关文章

  1. "红色病毒"问题 HDU 2065 递推+找循环节

    题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=2065 递推类题目, 可以考虑用数学方法来做, 但是明显也可以有递推思维来理解. 递推的话基本就是状态 ...

  2. HDU 1757 A Simple Math Problem 【矩阵经典7 构造矩阵递推式】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=1757 A Simple Math Problem Time Limit: 3000/1000 MS (J ...

  3. hdu 1757 A Simple Math Problem (构造矩阵解决递推式问题)

    题意:有一个递推式f(x) 当 x < 10    f(x) = x.当 x >= 10  f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + ...

  4. HDU - 2604 Queuing(递推式+矩阵快速幂)

    Queuing Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  5. hdu 5950 Recursive sequence 递推式 矩阵快速幂

    题目链接 题意 给定\(c_0,c_1,求c_n(c_0,c_1,n\lt 2^{31})\),递推公式为 \[c_i=c_{i-1}+2c_{i-2}+i^4\] 思路 参考 将递推式改写\[\be ...

  6. ZOJ 3182 HDU 2842递推

    ZOJ 3182 Nine Interlinks 题目大意:把一些带标号的环套到棍子上,标号为1的可以所以操作,标号i的根子在棍子上时,只有它标号比它小的换都不在棍子上,才能把标号为i+1的环,放在棍 ...

  7. 矩阵乘法&矩阵快速幂&矩阵快速幂解决线性递推式

    矩阵乘法,顾名思义矩阵与矩阵相乘, 两矩阵可相乘的前提:第一个矩阵的行与第二个矩阵的列相等 相乘原则: a b     *     A B   =   a*A+b*C  a*c+b*D c d     ...

  8. P1067Warcraft III 守望者的烦恼(十大矩阵问题之七求递推式)

    https://vijos.org/p/1067 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她 ...

  9. Tyche 2191 WYF的递推式

    题目描述 WYF手中有这样一条递推式 WYF并不是想让你帮他做出结果,事实上,给定一个n,他能够迅速算出Fn.WYF只是想单纯的考验一下读者们. 输入描述 仅一行,三个整数N,F1,P 输出描述 仅一 ...

随机推荐

  1. [转帖]【JVM 知识体系框架总结】

    [JVM 知识体系框架总结] https://www.cnblogs.com/mousycoder/p/11612448.html JVM 内存分布 线程共享数据区:方法区->类信息,静态变量堆 ...

  2. yum源出问题,rpmdb: BDB0113 Thread/process 17276/140338032428864 failed: BDB1507 Thread died in Berkeley DB library

    yum源出问题 cd /var/lib/rpm rm -f *db.* rpm --rebuilddb 重构了之后就可以用了

  3. oracle多表关联查询和子查询

    oracle多表关联查询和子查询 一.多表关联查询 例子: SQL> create table student1 ( sid ), sname ), sage )); Table created ...

  4. VUE创建项目

    Vue Cli项目搭建     vue项目需要自建服务器:node 什么是node: 用C++语言编写,用来运行JavaScript语言 node可以为前端项目提供server (包含了socket) ...

  5. python学习——while True的用法

    在学习过程中,经常能遇到采用while True的用法.下面以一个例子进行说明: 建立一个用户登录系统,用户输入用户名和密码,如果正确就可以进入系统. 1.我自己最开始的写法: d = {} #数据库 ...

  6. Python笔记002-Python编程基础概念

    第二章(1):Python编程基础概念 1. Python 程序的构成 Python 程序有模块组成.一个模块对应 Python 源文件,一般后缀名是:.py. 模块有语句组成.运行 Python程序 ...

  7. 使用Duilib开发Windows软件(4)——消息传递

    云信Duilib中没有窗体类的函数可以用来直接收取到所有控件的事件,每个控件都可以单独设置自己的事件处理函数,一般在InitWindow方法中初始化各个控件的事件处理函数. 每个控件都有许多形如Att ...

  8. spring中使用动态代理(AOP)

    spring是整合了BGLIB和JDK两种动态代理 示例:使用CGLIB代理 public class MyCar { private String color = "blue"; ...

  9. scratch少儿编程——03、动作:运动的开始,游戏的基础。

    各位小伙伴大家好: 从这一期开始我们来学Scratch的具体操作. 第一季我们会从每一个脚本模块开始.一个程序块一个程序块去操作,感受它的效果. 今天我们来一起学习程序区的脚本类动作模块的指令. 动作 ...

  10. element-ui 时间设置 获取固定的时间格式

    <el-date-picker v-model="time1" type="daterange" start-placeholder="开始日期 ...