同余方程有解的条件 && Cyclic Cipher题解

一.结论

对于 n 个同余方程组,如果两两有解,则一定有解满足 n 个方程组。

证明:(归纳法)

1.初始状态

attention:这里(初始状态部分)的 [] 都表示 lcm, () 都表示 gcd,就不大写了


我们先只考虑三个同余方程组.

假设三个同余方程组:(条件)

{Qa1(modm1)Qa2(modm2)Qa3(modm3)

由中国剩余定理,有以下基本结论:

{(m1,m2)|a1a2(m1,m3)|a1a3(m2,m3)|a2a3


引理1:

([a,b],c)=[(a,c),(b,c)]

考虑质因子 p, 它在 a,b,c 中幂次分别为 qa,qb,qc

{([a,b],c)=min(max(qa,qb),qc)[(a,c),(b,c)]=max(min(qa,qc),min(qb,qc))

暴力分类讨论 qa,qb,qc 的相对大小,容易得出 =


引理2:

{a|bb|ca|c

整除的传递性


引理3:

{a|cb|c[a,b]|c

考虑质因子 p,它在 a,b,c 中幂次分别为 qa,qb,qc

则由条件得:{qaqcqbqc

则:max(qa,qb)qc

则:[pqa,pqb]=pmax(qa,qb)|pqc

所以 [pqa,pqb]|pqc

对于所有的质因子,都有[pqa,pqb]|pqc,那么 [pqa,pqb]|pqc[a,b]|c


证明:

xa1(modm1),xa2(modm2),x[m1,m2]

x=a1+m1y

即证:{Qx(mod[m1,m2])Qa3(modm3) (扩展中国剩余定理)

即证:([m1,m2],m3)|xa3 (扩展中国剩余定理)

即证:[(m1,m3),(m2,m3)]|xa3 (引理1)

即证:{(m1,m3)|xa3(m2,m3)|xa2 (引理3)

我们只考虑 (m1,m3)|xa3(m2,m3)|xa2 同理

即证: (m1,m3)|a1+m1ya3

即证: (m1,m3)|a1a3+m1y

即证:{(m1,m3)|a1a3(m1,m3)|m1y

由引理2(整除的传递性):

即证:{(m1,m3)|a1a3(m1,m3)|m1m1|m1y

①:已证,在基本条件处

②:gcd 的性质

③:易证

得证。


2.归纳过程

attention: 这里 [l,r] 表示第 l 个到第 r 个方程合并后的方程。

f(i)=1,则表明合并后 ni 个方程后,有解。

欲证:若 f(i)=1 且方程两两有解, f(i+1)=1

考虑第 k 个方程

则:由初始状态的证明,有解同时满足第 k, i, i+1 个方程。

由扩展剩余定理,则第 ii+1 个方程合并后,还能与第 k 个方程合并。

令第 ii+1 个方程合并后的方程为 G,则 Gk 有解。

所以任意方程都与 G 有解,所以 i, i+1 合并后,如果有解能满足这 i 个同余方程(f(i)=1),则有解能满足这 i+1 个方程(f(i+1)=1


二.实现

有了结论,这道题就非常好做了。

因为操作时间非常长,大于 2lcm,所以一个周期里的情况都会出现。

枚举最长串的数字是 x,如果在时间 t[l,r] 这段子串同时出现 x,则 t 满足 tpi(modleni)i[l,r]leni 表示第 i 个序列的长度,pi 表示 x 在第 i 个序列出现的位置(从零开始编号))。

则我们跑所有 x 出现的行。

我们考虑用双指针 l,r

  1. 如果发现第 r 和第 r+1 不相邻,则 l=r

因为都不连续了,所以 l 可以直接赋为 r

  1. 长度(即模数)最大为 40,所以方程最多有 40 个 (如果模数一样,但是余数不一样,则无解)。

我们用 STL 保存下来所有同余方程,每次 r++

假设我们现在的 r对应的长度为 lenx 出现在 p 号位置。

  1. 如果len 没出现过,就暴力扫一遍所有的同余方程,看看都能不能和新方程(tp(modlen))合并,不满足就 l++,直到与之矛盾的方程消失为止。

  2. 如果len 出现过,就判断新余数和之前出现的模数相同的方程的余数是否相同,不相同就 l++,直到没有模数为 len 的方程(除了这个新的方程) 。

但是!!!由于 Excrt 可以判断出余数不同的情况,所以我们就不需要写这个判断了(写了代码也不长)。

时间复杂度均摊下来是: O(40log240leni)

三.参考代码

#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int> 
#define MP(x,y) (make_pair (x, y))

template <typename T> void read (T &x) { x = 0; T f = 1;char tem = getchar ();while (tem < '0' || tem > '9') {if (tem == '-') f = -1;tem = getchar ();}while (tem >= '0' && tem <= '9') {x = (x << 1) + (x << 3) + tem - '0';tem = getchar ();}x *= f; return; }
template <typename T> void write (T x) { if (x < 0) {x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0'); }
template <typename T> void print (T x, char ch) { write (x); putchar (ch); }
template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }

const int Maxn = 1e5;
const int Maxlen = 40;

int n, m;
int len[Maxn + 5]; 
int a[Maxn + 5][Maxlen + 5];

vector <PII> v[Maxn + 5];
int bak[Maxn + 5], b[Maxn + 5];
LL gcd (LL x, LL y) {
	if (y == 0) return x;
	else return gcd (y, x % y);
}
bool check (int m1, int b1, int m2, int b2) {
	return (b1 - b2) % gcd (m1, m2) == 0;
}

int main () {
	read (n); read (m);
	for (int i = 1; i <= n; i++) {
		read (len[i]);
		for (int j = 0; j < len[i]; j++)
			{ read (a[i][j]); v[a[i][j]].push_back (MP (i, j)); }
	}
	
	for (int i = 1; i <= m; i++) {
		memset (bak, 0, sizeof bak);
		int l = 0, r = 0, ans = 0; 
		while (r < (int)v[i].size ()) {
			int idx = v[i][r].first, Mod = len[idx], p = v[i][r].second;
			if (r != 0 && idx != v[i][r - 1].first + 1)
				while (l < r) 
					bak[len[v[i][l++].first]]--;
			for (int j = 1; j <= 40; j++) {
				if (bak[j] >= 1 && check (j, b[j], Mod, p) == 0) {
					while (bak[j])
						{ bak[len[v[i][l++].first]]--; }
				}
			}
			bak[Mod]++;
			b[Mod] = p;
			ans = Max (ans, r - l + 1);
			r++;
		}
		printf ("%d\n", ans);
	}
	return 0;
}
posted @   C2022lihan  阅读(550)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示