题目传送门:洛谷 P5345

很荣幸为 X Round 1 贡献了自己的一题。

题意简述:

给定 \(n\) 组 \(k_i,g_i,r_i\)(\(0\le k_i,r_i<g_i\le 10^7\))。

求关于 \(x\) 的方程组 \(\left\{\begin{matrix}k_1^x\equiv r_1\pmod{g_1}\\k_2^x\equiv r_2\pmod{g_2}\\\vdots\\k_n^x\equiv r_n\pmod{g_n}\end{matrix}\right.\)(定义 \(0^0=1\))在 \([0,10^9]\) 内的最小整数解,或判断在这个范围内无解。

题解:

分为两个部分解决。

第一部分:分别求出每个方程的解。

首先观察 \(k^j\bmod g\) 的规律,以 \(g=495616\),\(k=124\) 为例:

定义 \(f(i)=ki\bmod g\),则把每个在 \([0,g)\) 之间的整数看作一个节点后,形成了一个基环内向森林。

从 \(1\bmod g\) 开始走唯一的出边,必然形成一个 \(\rho\) 形结构,让我们模拟这个过程:

可以看到,出现了长度为 \(5\) 的循环。

  1. 如果 \(r=245760\),则 \(x\equiv 7\pmod{5}\),且 \(x\ge 7\)。

  2. 如果 \(r=12544\),则 \(x=4\)。

  3. 如果 \(r=2\),则无解。

以上就是每个方程的 \(3\) 种解,无限解,唯一解或无解。

那么,问题就是,如何区分这 \(3\) 种解,以及如何求出解。

首先,需要将 \(\rho\) 形的“尾巴”和循环分开考虑,不难证明“尾巴”的长度不超过 \(\log_2g\)。

而且可以发现,若在“尾巴”上找到了解,那么就只有一组解。所以需要判断一个值是否在尾巴上。

其实这是很简单的,如果 \(\gcd(x,m)\neq\gcd(f(x),m)\),那么 \(x\) 就在尾巴上,反之就在循环内。

据此,我们区分了在“尾巴”上的解,也就是只有一组解的情况,接下来考虑不在“尾巴”上的情况。

因为解不在“尾巴”上,则如果解不在循环内就是无解了,所以首先判断解是否在循环内。

假设第一个在循环上的数为 \(c\),尾巴长度为 \(o\),则有 \(c\equiv k^o\pmod{g}\)。

令 \(d=\gcd(c,g)\),则原方程 \(k^x\equiv r\pmod{g}\) 可化为 \(c\cdot k^{x-o}\equiv r\pmod{g}\) 且 \(x\ge o\),这是因为我们假定解一定在循环内。

可以进一步化为 \(k^{x-o}\equiv\frac{r}{d}\left(\frac{c}{d}\right)^{-1}\pmod{\frac{g}{d}}\),若 \(r\) 不是 \(d\) 的倍数则无解。

这是因为循环内的值均是 \(d\) 的倍数,可以让方程同除 \(d\),又因为 \(\frac{c}{d}\perp\frac{g}{d}\),可以取逆元。

令 \(a=k,b=\frac{r}{d}\left(\frac{c}{d}\right)^{-1},m=\frac{g}{d}\),则有 \(a\perp m\)。

使用 BSGS 求出 \(a^y\equiv b\pmod{m}\) 的最小自然数解 \(y\) 后,有原方程的最小自然数解为 \(y+o\)。

再使用 BSGS 求出 \(a^z\equiv 1\pmod{m}\) 的最小正整数解 \(z\),即 \(a\) 对 \(m\) 的阶。

则原方程的解为 \(x\equiv y+o\pmod{z}\) 且 \(x\ge y+o\)。

至此,第一部分解决。

第二部分:合并每个方程的解。

首先,若前面的方程出现了无解的情况,则方程组也无解。

若前面的方程出现了只有唯一解的情况,只需要检查此唯一解是否满足所有方程即可。

接下来讨论以上每个方程的解均形如 \(x\equiv r\pmod{q}\) 且 \(x\ge r\) 的形式。

分开考虑前半部分和后半部分,对于前半部分,显然是 ExCRT 的形式。

对于后半部分,可以化为 \(x\ge\max r_i\),令 \(\max r_i=x_0\),放到最后考虑。

考虑使用 ExCRT 解决前半部分,令前 \(i\) 个方程组的解为 \(x\equiv P_i\pmod{Q_i}\),有 \(P_0=0,Q_0=1\)。

但是这里出现一个问题,那就是 \(P_i,Q_i\) 可能很大,但是这里其实没必要使用高精度,要怎么处理这种情况呢?

因为以上方程的解 \(x\equiv r\pmod{q}\) 中,\(q\) 均小于 \(10^7\),所以不需要担心这部分。

考虑这样一种情况:\(Q_{i-1}>10^9\),而再合并进 \(x\equiv r_i\pmod{q_i}\) 可能会让 \(Q_i\) 超出 long long 能够表示的范围。

这时其实不需要再合并了,只需要判断 \(P_{i-1}\) 是否满足第 \(i\) 个方程即可。因为若不满足,合并后 \(x\) 必然会至少增加一倍的 \(Q_{i-1}\),这就超出了 \(10^9\) 的范围,从而可以直接输出无解。

最后,当方程成功合并完之后,\(Q_n\) 可能不是真实值,但是当 \(Q_n\le 10^9\) 时必然是真实值。

此时可以再考虑 \(x_0\),真实的解应该为 \(x=\left\lceil\frac{x_0-P_n}{Q_n}\right\rceil\cdot Q_n+P_n\)。

若 \(Q_n> 10^9\),则必然要满足 \(P_n\ge x_0\),否则无解。

据此写出代码,复杂度 \(\mathcal{O}\left(\sum_{i=1}^{n}\left(\sqrt{g_i}+\log g_i\right)\right)\):

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath> #define Fail return puts("Impossible"), 0
#define mp std::make_pair typedef long long LL;
typedef std::pair<int, int> pii;
const int MG = 10000005, MS = 3175;
const int U = 1e9; int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } template<typename T>
T exgcd(T a, T b, T &x, T &y) {
if (!b) return x = 1, y = 0, a;
int d = exgcd(b, a % b, y, x);
return y -= a / b * x, d;
} int buk[MG], stk[MS];
inline int BSGS(int a, int b, int m) {
int S = sqrt(m - 1) + 1;
int A = 1, f = -1, t = 0;
for (int i = 0; i < S; ++i) {
buk[stk[++t] = (LL)b * A % m] = i;
A = (LL)A * a % m;
}
int C = 1;
for (int i = 1; !~f && i <= S; ++i)
if (~buk[C = (LL)C * A % m])
f = i * S - buk[C];
while (t) buk[stk[t--]] = -1;
return f;
} inline pii ExBSGS(int a, int b, int m) {
int o = 0, A = 1 % m, d = 1, nd, x, y;
while (1) {
if (d == (nd = gcd((LL)A * a % m, m))) break;
if (A == b) return mp(o, -1);
++o, A = (LL)A * a % m, d = nd;
}
if (b % d) return mp(-1, -1);
m /= d, b /= d, A /= d;
exgcd(A, m, x, y);
b = (LL)b * (x + m) % m;
x = BSGS(a, b, m);
if (!~x) return mp(-1, -1);
y = BSGS(a, 1 % m, m);
return mp(x % y + o, y);
} inline bool Combine(LL &a1, LL &m1, LL a2, LL m2) {
LL k1, k2, g = exgcd(m1, m2, k1, k2);
if ((a2 - a1) % g) return 0;
a1 += (k1 * ((a2 - a1) / g) % m2 + m2) * m1 % (m1 / g * m2);
return a1 %= m1 *= m2 / g, 1;
} const int MN = 1005; int N;
int k[MN], r[MN], g[MN];
int x[MN], q[MN], X, MaxX; int main() {
memset(buk, -1, sizeof buk), X = -1;
scanf("%d", &N);
for (int i = 1; i <= N; ++i) {
scanf("%d%d%d", &k[i], &g[i], &r[i]);
pii ans = ExBSGS(k[i] % g[i], r[i] % g[i], g[i]);
x[i] = ans.first, q[i] = ans.second;
if (!~x[i]) Fail;
if (!~q[i]) X = x[i];
MaxX = std::max(MaxX, x[i]);
}
if (~X) {
for (int i = 1; i <= N; ++i) {
if (~q[i] && (X < x[i] || (X - x[i]) % q[i])) Fail;
if (!~q[i] && X != x[i]) Fail;
}
return printf("%d\n", X), 0;
}
LL P = 0, Q = 1;
for (int i = 1; i <= N; ++i) {
if (Q > U && (P - x[i]) % q[i]) Fail;
if (Q <= U && !Combine(P, Q, x[i] % q[i], q[i])) Fail;
}
if (P < MaxX) P += ((MaxX - P - 1) / Q + 1) * Q;
if (P > U) Fail;
printf("%lld\n", P);
return 0;
}

洛谷 P5345: 【XR-1】快乐肥宅的更多相关文章

  1. 洛谷 P1271 聚会的快乐(树状dp)

    题目描述 你要组织一个由你公司的人参加的聚会.你希望聚会非常愉快,尽可能多地找些有趣的热闹.但是劝你不要同时邀请某个人和他的上司,因为这可能带来争吵.给定N个人(姓名,他幽默的系数,以及他上司的名字) ...

  2. 洛谷 P5706 【深基2.例8】再分肥宅水

    题目连接: P5706 [深基2.例8]再分肥宅水 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 我提交的: 1 #include<iostream> 2 #inclu ...

  3. 洛谷$P4040\ [AHOI2014/JSOI2014]$宅男计划 贪心

    正解:三分+贪心 解题报告: 传送门$QwQ$ 其实很久以前的寒假就考过了,,,但那时候$gql$没有好好落实,就只写了个二分,并没有二分套三分,就只拿到了$70pts$ #include <b ...

  4. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  5. 洛谷1352 CODEVS1380 没有上司的舞会

    洛谷的测试数据貌似有问题,4个点RE不可避 CODEVS可AC —————— 10分钟后追记:在洛谷把数组范围开到10000+就过了 —————— 题目描述 Description Ural大学有N个 ...

  6. BZOJ5291/洛谷P4458/LOJ#2512 [Bjoi2018]链上二次求和 线段树

    原文链接http://www.cnblogs.com/zhouzhendong/p/9031130.html 题目传送门 - LOJ#2512 题目传送门 - 洛谷P4458 题目传送门 - BZOJ ...

  7. 洛谷 p1352 没有上司的舞会 题解

    P1352 没有上司的舞会 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员 ...

  8. 洛谷 P4592: bzoj 5338: [TJOI2018]异或

    题目传送门:洛谷P4592. 题意简述: 题面说的很清楚了. 题解: 发现没有修改很快乐.再看异或最大值操作,很容易想到可持久化 01trie. 这里要把 01trie 搬到树上,有点难受. 树剖太捞 ...

  9. 洛谷P1331海战

    题目描述 在峰会期间,武装部队得处于高度戒备.警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机.此外,巡洋船只和舰队将被派去保护海岸线. 不幸的是因为种种原因,国防海军部仅有很少的 ...

随机推荐

  1. List Map Set的线程安全

    常见的ArrayList  LinkedList  HashMap TreeMap LinkedHashMap HashSet TreeSet LinkedHashSet 都是线程不安全的.如果要使用 ...

  2. docker 学习操作记录 4

    记录3 [BEGIN] // :: Connecting to ... Connection established. To escape to local shell, press Ctrl+Alt ...

  3. Java的多路分支代码,感觉有点意思

    /** * @Author hty * @Date 2019-12-16 16:39 * @Version 1.0 */ import java.util.Random; // 比赛结果 enum O ...

  4. GIT 安装和使用

    目录 GIT 安装和使用 一.GIT 介绍 二.GIT 安装 三.GIT 使用 1. 配置 2. 创建版本库 3. 远程仓库 4. 分支管理 5.标签管理 6. 自定义 GIT 安装和使用 一.GIT ...

  5. mybatis-plus 主键自增问题

    主键不自增:返回值是插入的条数 <insert id="add" parameterType="EStudent"> insert into TSt ...

  6. JAVAWEB之增删改查

    青年志愿者服务网(20分)   1.项目需求: 为了适应社会主义市场经济发展的需要,推动青年志愿服务体系和多层次社会保障体系的建立和完善,促进青年健康成长,石家庄铁道大学急需建设青年志愿者服务网,推进 ...

  7. JavaScript由来

    在互联网时代,网速还很差劲的时候,表单输入数据的合法性验证需要与服务器交换数据,从而加重了使用者的负担. 网景公司为了解决这种简单问题开发了JavaScript.在1995年2月网景公司在发布自己的浏 ...

  8. Echarts 学习系列(1)-5分钟上手ECharts

    目录 写在前面 下载Echarts和主题 绘制一个简单的图表 写在前面 最近,在做某个项目的时候.需要使用的可视化的图表显数据.最后,选择了百度的Echarts. 下载Echarts和主题 1.获取E ...

  9. 18 java I/O 系统

    流的类继承结构 我们首先看看流的类继承结构,有助于理解下个标签的内容 InputStream OutputStream Reader Writer File类 File类技能表示一个特定文件的名称,又 ...

  10. 无法打开内核设备:\\Global\\vmx86

    关于如题目的问题,网上有好几个解决办法,这里只介绍最方便的一个办法,利用脚本来解决 @Echo Off title Hankcs's program color 8F CD %~d0 CD %~dp0 ...