理论部分

二次剩余

在数论中,整数 $X$ 对整数 $p$ 的二次剩余是指 $X^2$ 除以 $p$ 的余数。

当存在某个 $X$,使得式子 $X^2 \equiv d(mod \ p)$ 成立时,称“ $d$ 是模 $p$ 的二次剩余”

当对任意 $X$,$X^2 \equiv d(mod \ p)$ 都不成立时,称“ $d$ 是模 $p$ 的二次非剩余”

矩阵的相似对角化

相似矩阵:对于矩阵 $A$ 和 $B$,若存在可逆矩阵 $P$,使得 $P^{-1}AP=B$,则称 $A$ 相似于 $B$,记作 $A\sim B$。

矩阵可对角化是指与对角矩阵相似,即 $P^{-1}AP = diag(\lambda _1, \lambda _2,...,\lambda _n)$

定理:$n$ 阶矩阵 $A$ 与对角矩阵相似的充要条件是 $A$ 有 $n$ 个线性无关的特征向量。简单的判断就是 $|A| \neq 0$.

分析

来源于 acdreamers 的广义Fibonacci数列找循环节,这里只是梳理一下。

将递推式表示成转移矩阵的形式,相当于只需找到转移矩阵的周期。

即求最小的 $n$,使得

$${\begin{bmatrix} a & b\\ 1 & 0 \end{bmatrix}}^n(mod \ p) = \begin{bmatrix} 1 & 0\\ 0 & 1 \end{bmatrix}$$

我们可以找到一个满足条件的 $n$,然后枚举其因子。

设 $A$ 相似于 $D$,$A$ 的特征根分别为 $\lambda _1,\lambda _2$.

则D为

$D = \begin{bmatrix} \lambda _1 & 0\\  0 & \lambda _2 \end{bmatrix}$

因为 $A^n = T^{-1}D^nT$,所以 $D^n \equiv I(mod \ p)$ 时,$D^n \equiv I(mod \ p)$

由于$$D^n = {\begin{bmatrix} \lambda _1 & 0\\  0 & \lambda _2 \end{bmatrix}}^n = \begin{bmatrix} \lambda _1^n & 0\\  0 & \lambda _2^n \end{bmatrix}(mod \ p) = I$$

于是 $\lambda _1^n\equiv 1(mod \ p),\ \lambda _2^n\equiv 1(mod \ p)$.

如何找到 $n$ 呢?

直接上结论吧!(看不懂了555)

设 $\Delta  = a^2+4b$

  • 若 $\Delta$ 是 $p$ 的二次剩余,$n=p-1$
  • 若 $\Delta$ 是 $p$ 的二次非剩余,$n=(p+1)(p-1)$
  • 若 $\Delta=p$,则无法相似化。幸好题目不会出现这种情况

上述结论还是针对 $p$ 为素数,$p$ 为合数呢?

首先,质因数分解 $p=p_1^{a_1}p_2^{a_2}...p_k^{a_k}$,

设 $g(x)$ 为模 $x$ 时循环节长度,有结论 $g(p_i^{a_i}) = p_i^{a_1-1} g(p_i)$

所以

$$
\begin{aligned}
g(x) & =g(p_1^{a_1}p_2^{a_2}...p_k^{a_k})\\
&= p_1^{a_1-1} g(p_1) \cdot  p_2^{a_2-1} g(p_2) ...  p_k^{a_k-1} g(p_k)\\
&= (p / p_1p_2... p_k) g(p_1)g(p_2) ...   g(p_k)
\end{aligned}$$

实现

二次剩余我又不会判断,直接当作 $(p+1)(p-1)$,大不了多个倍数。

按道理最小的循环节不是 $n$,而是 $n$ 的因数,感觉分解再判断挺麻烦的,不管了,大不了多个倍数。

  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. }

参考链接:

1. 分析: https://blog.csdn.net/acdreamers/article/details/25616461

2. 代码:https://www.cnblogs.com/LMCC1108/p/11286388.html

2019牛客多校第五场 generator 1——广义斐波那契循环节&&矩阵快速幂的更多相关文章

  1. 2019牛客多校第五场generator2——BSGS&&手写Hash

    题目 几乎原题 BZOJ3122题解 分析 先推一波公式,然后除去特殊情况分类讨论,剩下就是形如 $a^i \equiv b(mod \ p)$ 的方程,可以使用BSGS算法. 在标准的BSGS中,内 ...

  2. 2019牛客多校第五场F maximum clique 1 最大独立集

    题意:给你n个数,现在让你选择一个数目最大的集合,使得集合中任意两个数的二进制表示至少有两位不同,问这个集合最大是多大?并且输出具体方案.保证n个数互不相同. 思路:容易发现,如果两个数不能同时在集合 ...

  3. 2019牛客多校第五场G-subsequence 1 DP

    G-subsequence 1 题意 给你两个字符串\(s.t\),问\(s\)中有多少个子序列能大于\(t\). 思路 令\(len1\)为\(s\)的子序列的长度,\(lent\)为\(t\)的长 ...

  4. 2019牛客多校第五场 B - generator 1 矩阵快速幂+十倍增+二进制倍增优化

    B - generator 1 题意 给你\(x_{0}.x_{1}.a.b.b.mod\),根据\(x_{i} = a*x_{i-1} + b*x_{i-2}\)求出\(x_{n}\) 思路 一般看 ...

  5. 2019牛客多校第五场H - subsequence 2 拓扑

    H - subsequence 2 题意 要你使用前\(m\)个小写字母构造一个长度为\(n\)的字符串 有\(m*(m-1)/2\)个限制条件: \(c_{1} .c_{2}. len\):表示除去 ...

  6. 2019牛客多校第五场B-generator 1(矩阵快速幂)

    generator 1 题目传送门 解题思路 矩阵快速幂.只是平时的矩阵快速幂是二进制的,这题要用十进制的快速幂. 代码如下 #include <bits/stdc++.h> #defin ...

  7. 2019 牛客多校第五场 B generator 1

    题目链接:https://ac.nowcoder.com/acm/contest/885/B 题目大意 略. 分析 十进制矩阵快速幂. 代码如下 #include <bits/stdc++.h& ...

  8. 2019牛客多校第五场 G subsequence 1 dp+组合数学

    subsequence 1 题意 给出两个数字串s,t,求s的子序列中在数值上大于t串的数量 分析 数字大于另一个数字,要么位数多,要么位数相同,字典序大,位数多可以很方便地用组合数学来解决,所以只剩 ...

  9. 2019牛客多校第五场 F maximum clique 1 状压dp+最大独立集

    maximum clique 1 题意 给出一个集合s,求每个子集的最大独立集的权值和(权值是独立集的点个数) 分析 n比较小,一股浓浓的暴力枚举每一个子集的感觉,但是暴力枚举模拟肯定会T,那么想一想 ...

随机推荐

  1. [转帖]Greenplum: 基于PostgreSQL的分布式数据库内核揭秘(下篇)

    Greenplum: 基于PostgreSQL的分布式数据库内核揭秘(下篇) http://www.postgres.cn/v2/news/viewone/1/454 原作者:姚延栋 创作时间:201 ...

  2. Python 实现把两个排好序的的列表合并成一个排序列表

    列表是升序的 # -*- coding: utf-8 -*- # 合并两个排序的数组 def merge_list(a, b): if not a: return b if not b: return ...

  3. (十)EL表达式和JSTL标签快速入门

    目录 什么是 el 表达式 示例:使用EL表达式获取pageContext .request.session.application域中的数据: 示例:使用EL表达式获取Bean属性 获取当前WEB应 ...

  4. Centos6.5镜像下载

    CentOS6.5系统安装 1.首先打开网易开源镜像站: http://mirrors.163.com/ 当然,大家也可以使用阿里开源镜像站:http://mirrors.aliyun.com/ 2. ...

  5. 值得收藏的Python第三方库

    网络站点爬取 爬取网络站点的库Scrapy – 一个快速高级的屏幕爬取及网页采集框架.cola – 一个分布式爬虫框架.Demiurge – 基于PyQuery 的爬虫微型框架.feedparser ...

  6. Python--字典的一些用法dict.items()

    1.dict.items() 例子1: 以列表返回可遍历的(键, 值) 元组数组. dict = {'Name': 'Runoob', 'Age': 7} print ("Value : % ...

  7. Redis键的序列化和反序列化

    序列化 命令名称:DUMP 语法:DUMP key 功能:序列化给定key,并返回被序列化的值.序列化的值不包括任何生存时间信息. 返回值:如果key不存在,那么返回nil.否则返回序列化之后的值 反 ...

  8. 写给Web开发人员看的Nginx介绍

    译者注:不知道其他开发者是否和我一样,参与或者写了很多Web项目,但是却没有真正的去完整的部署应用,很多时候都是交给ops即运维的同学帮忙来做.而作为一个有节操的开发者,我认为了解一些服务器方面的知识 ...

  9. Java QuickSort 快速排序

    Java QuickSort /** * <html> * <body> * <P> Copyright 1994-2018 JasonInternational ...

  10. sftp配置多个用户权限的问题

    groupadd group1 chmod 0755 /test/useradd -g group1 -d /test/backend/ -M test_backendusermod -s /sbin ...