前言

数学符号约定

  1. \(a,b,p\):表示任意自然数。
  2. \(F_x\):表示广义斐波那契数列的第 \(x\) 项。
  3. \(f_x\):表示普通斐波那契数列的第 \(x\) 项.

如非特殊说明,将会按照上述约定书写符号。

题目分析

首先引入一条定理:

普通斐波那契数列在模 \(m\) 意义下纯循环,且循环节为 \(O(m)\)。

证明可以去看 wlzhouzhuan 的博客,碍于篇幅限制不多赘述。

然后我们定义 \(F_0 = a,\, F_1 = b\),则显然我们有:\(F_p = af_{p-1} + bf_{p}\),证明平凡,如果想不出来可以手玩一下试试。

此时,我们的目标是对于 \(a,b\) 求出 \(p\) 使其满足下式:

\[af_{p-1} + bf_p \equiv 0 \pmod {m}
\]

移项,得:

\[af_{p-1} \equiv -bf_p \pmod m
\]

此时,我们不妨令 \(t = -b\),则我们有:

\[af_{p-1} \equiv tf_p \pmod m
\]

观察上式,发现如果我们能将 \(f_{p-1}\) 和 \(t\) 分别移项,然后预处理 \(\dfrac {f_p}{f_{p-1}}\) 问题就十分的简单了,但是因为 \(m\) 不为质数(即两者不一定互质),故我们不能这么做。

然而,俗话说的好,没有条件就让我们创造条件,先考虑对原式化简,设 \(d = \gcd(a,t,m)\),则原式变为:

\[\frac{a}{d} f_{p-1} \equiv \frac{t}{d} f_p \pmod {\frac{m}{d}}
\]

如果我们想让 \(\dfrac td\) 在 \(\dfrac md\) 的情况具有逆元,则需要保证 \(\dfrac td \perp \dfrac md\),但是此时显然不一定成立,于是我们设 \(d' = \gcd(\dfrac td, \dfrac md)\),现在考虑同余式左侧应该如何除以 \(d'\)。思考 \(d'\) 此时是 \(\dfrac td\) 和 \(\dfrac md\) 的公共因子,因为 \(d\) 已经是 \(a,t,m\) 的最大公因数了,则此时 \(\dfrac ad,\dfrac td,\dfrac md\) 之间已经不存在公共因子了,若 \(d' \not \perp a\),则说明 \(\dfrac ad,\dfrac td,\dfrac md\) 之间还存在公共因子 \(d'\),与条件相悖,故 \(d' \perp a\)。

因为同余式左侧一定是 \(d'\) 的倍数(否则无法构成同余关系),故得证 \(d' \mid f_{p-1}\),换言之,就是 \(d'\) 一定会整除在 \(f_{p-1}\) 身上。于是式子变为:

\[\begin{aligned}
\frac{a}{d} \frac{f_{p-1}}{d'} \equiv \frac{t}{dd'} f_p \pmod {\frac{m}{dd'}}\\
\frac{a}{d} \left( \frac{t}{dd'}\right) ^ {-1} \frac {f_{p-1}}{d'} \equiv f_p \pmod {\frac{m}{dd'}}
\end{aligned}
\]

好,现在我们再考虑能否将 \(\dfrac {f_{p-1}}{d'}\) 移项过去,要移项则必须保证 \(\dfrac{f_{p-1}}{d'} \perp \dfrac{m}{dd'}\),因为斐波那契数列具有性质 \(f_{p-1} \perp f_{p}\),并且我们又要必须保证右侧应当为 \(\gcd(\dfrac{f_{p-1}}{d'},\dfrac{m}{dd'})\) 的倍数,自然此时 \(\gcd(\dfrac{f_{p-1}}{d'},\dfrac{m}{dd'}) = 1\),故存在逆元,可以进行移项。

于是我们可以预处理三元组 \(\left( d,d',\dfrac{f_p}{\dfrac{f_{p-1}}{d'}} \bmod {\dfrac{m}{dd'}} \right)\),并用一个 map 来维护它。但是复杂度就直接飙升到令人无法接受的 \(O((\sum_{d \mid m}\sum_{d' \mid d} 1 )\log m)\)。于是我们考虑探究其中的性质。

我们回过头来看原先所写的 \(d' \mid f_{p-1}\),发现如果分两步枚举 \(d'\) 是非常笨的,因为我们还有 \(d' \mid \dfrac md\),我们又有 \(\gcd(\dfrac{f_{p-1}}{d'},\dfrac{m}{dd'}) = 1\),于是显然我们此时的 \(d'\) 只能等于 \(\gcd(f_{p-1},\dfrac md)\),故只需要枚举 \(d\) 和 \(p\) 就可以得到全部的三元组,此时的时间复杂度是 \(O(\sigma (m) \log m)\) 的,因为渐近意义下 \(\sigma(m)\) 是等价于 \(m \log \log m\) 的(具体证明参见 chenxia25 - P7325,所以枚举部分的复杂度是 \(O(m\log\log m \log m)\) 的,总时间复杂度为 \(O((m\log\log m+n)\log m)\)

注意:

  • 若 \(f_{p-1}\) 和 \(f_p\) 等于 \(0\) 的时候我们的同余式就爆炸了,于是我们需要把这个特判掉。

代码实现

下面给出了关键部分的代码实现。

n=read();
m=read();
f[1] = 1;
for(int d = 1;d<m;++d){
if(m%d==0){
for(int p=2;p;++p){
f[p] = (f[p-2] + f[p-1]) % (m/d);
if(f[p-1] == 0 && f[p] == 1)
break;
if(!f[p-1] || !f[p])
continue;
int dd = __gcd(f[p-1],m/d);
int val = 1 * f[p] * inv(f[p-1]/dd,m/dd/d) % (m/dd/d);
if(!hashtable[make_tuple(d,dd,val)])
hashtable[make_tuple(d,dd,val)] = p;
}
}
}
for(int i=1;i<=n;i++){
a=read();
b=read();
if(a==0){
printf("0\n");
continue;
}
if(b==0){
printf("1\n");
continue;
}
b=(m-b)%m;
int d = __gcd(a,__gcd(b,m));
int dd = __gcd(b/d, m/d);
int val = 1ll * a / d * inv(b/d/dd,m/d/dd) % (m/d/dd);
int data = hashtable[make_tuple(d,dd,val)];
if(!data)
printf("-1\n");
else
printf("%lld\n",data);
}

题解 P7325的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream

    伪 分布模式下启动spark报错 从spark1.4以后,所有spark的编译都是没有将hadoop的classpath编译进去的,所以必须在spark-env.sh中指定hadoop中的所有jar包 ...

  2. KVM VM 添加 usb 设备

    制作xml文件 参考链接:https://libvirt.org/formatdomain.html#usb-pci-scsi-devices <hostdev mode='subsystem' ...

  3. linux top中 VSS,RSS,PSS,USS 4个字段的解读

    参考文章:linux中top命令 VSS,RSS,PSS,USS 四个内存字段的解读

  4. Xshell远程连接虚拟机及连接故障排查

    用Xshell 远程连接虚拟机 如果按前面博客装好虚拟机,会发现刚装好的虚拟机直接连Xshell连不上,宿主机也ping不通虚拟机,这就需要修改VMware的默认网络配置 修改步骤: 1.在VMwar ...

  5. docker下nginx配置

    一步一坑安装docker  nginx 首先选择适当版本镜像下载 我选的: nginx:1.16.0 docker pull nginx:1.16.0 安装完毕之后创建挂载文件夹 : mkdir /u ...

  6. Cilium系列-13-启用XDP加速及Cilium性能调优总结

    系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换/功能的启用, ...

  7. .NET ORM 鉴别器 和 TDengine 使用 -SqlSugar

    SqlSugar ORM SqlSugar 是一款 老牌 .NET 开源多库架构ORM框架 ,一套代码能支持多种数据库像像Admin.net.Blog.Core.CoreShop等知名开源项目都采用了 ...

  8. c++算法之离散化例题

    离散化基础2 题目描述 给定 n 个元素的数列,将相同的数据离散化为一个数据(去重),即把 {4000,201,11,45,11}{4000,201,11,45,11} 离散化为 {4,3,1,2,1 ...

  9. [ABC132D] Blue and Red Balls

    2023-01-16 题目 题目传送门 翻译 翻译 难度&重要性(1~10):3 题目来源 AtCoder 题目算法 dp 解题思路 因为蓝球的数量是固定的,题目让我们求,在取 \(i\) 次 ...

  10. 系统内存管理:虚拟内存、内存分段与分页、页表缓存TLB以及Linux内存管理

    虚拟内存 虚拟内存是一种操作系统提供的机制,用于将每个进程分配的独立的虚拟地址空间映射到实际的物理内存地址空间上.通过使用虚拟内存,操作系统可以有效地解决多个应用程序直接操作物理内存可能引发的冲突问题 ...