[笔记] CRT & exCRT

构造法

求多组\(x \equiv r_i (\bmod d_i)\)的解,\(d_i\)互质

余数\((r_i = remainder)\),除数\((d_i=divisor)\)

我们想啊,如果我们能找到一个数 \(k1\equiv1(mod\text{ }3)\)是 \(5\) 和 \(7\) 的倍数

一个数 $k2\equiv1(mod\text{ }5) $是\(3\)和\(7\)的倍数

一个数 $k3\equiv1(mod\text{ }7) $是\(3\)和\(5\)的倍数

那么这样的话我们的答案就是 \(k1*2+k2*3+k3*2\)

这样的话就是如何求这三个数了

首先我们求出 \(3,5,7\) 的$ lcm=105$

之后令

\(x1=105/3=35,x2=105/5=21,x3=105/7=15\)

我们可以得到三个线性同余方程

\(35a\equiv1(mod\text{ }3)\)

\(21b\equiv1(mod\text{ }5)\)

\(15c\equiv1(mod\text{ }7)\)

直接上扩欧就行了

所以$ k1=35a=35*2=70$

\(k2=21b=21∗1=21\)

\(k3=15c=15∗1=15\)

之后我们的答案就是

\((k1∗2+k2∗3+k3∗2)\bmod lcm=23\)

曹冲养猪

板子from wzx(我的构造法过不了,不过有了扩欧也不想用这个方法了)

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define re register
#define maxn 25
using namespace std;
inline LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b)
{
x=1,y=0;
return a;
}
LL r=exgcd(b,a%b,y,x);
y-=a/b*x;
return r;
}
inline LL read()
{
char c=getchar();
LL x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-48,c=getchar();
return x;
}
LL a[maxn],b[maxn];
LL x,y;
int n;
LL lcm=1;
int main()
{
n=read();
for(re int i=1;i<=n;i++)
{
b[i]=read();
a[i]=read();
lcm*=b[i];
}
LL ans=0;
for(re int i=1;i<=n;i++)
{
LL xx=lcm/b[i];
LL r=exgcd(xx,b[i],x,y);
x=(x%b[i]+b[i])%b[i];
ans=(ans+x*xx*a[i]%lcm)%lcm;
}
cout<<ans<<endl;
return 0;
}

扩欧法

\[\begin{cases}
x &\equiv& r_1 \pmod{d_1}\\
x & \equiv& r_2 \pmod{d_2}\\
&\vdots\\
x & \equiv& r_n \pmod{d_n}
\end{cases}\]

此时如果\(d_1,d_2,\dots,d_n\)不互质怎么办?

观察两个同余式

  • $x\equiv r_1 \pmod{d_1} $
  • \(x\equiv r_2 \pmod{d_2}\)

可以化为

  • \(x=k_1d_1 + r_1\)
  • \(x=k_2d_2+r_2\)

因此

  • \(k_2d_2+r_2=k_1d_1+r_1\)
  • \(k_2d_2-k_1d_1=r_1-r_2\)

是不是有点像\(ax+bx=c\)

于是我们可以解出来

  • \(k_2 ^{'} d_2+k_1 ^{'} d_1=gcd(d_1,d_2)\)

并乘上\((r_1-r_2)/gcd(d_1,d_2)\)得到之前式子的解

  • \(k_1=k_1 ^{'} \cdot (r_1-r_2)/gcd(d_1,d_2)\)

但是得\(gcd(d_1,d_2)|(r_1-r_2)\),不然是得不到通解的

因为是带着一个负号的,所以得到

  • \(x_0= -k_1d_1+r_1\)

得到新方程\(x\equiv x_0 \pmod{ lcm(d_1,d_2)}\)

好的,开始,抠细节

  • 首先,最后要取模\(lcm(d1,d2)\),快速乘的时候忘记了,挂掉x1
  • 快速乘里面不能有负数,挂掉x2
  • 快速乘也要取模\(lcm(d_1,d_2)\),挂掉x3
  • \(lcm(d_1,d_2)\)应该这么写,\(d_1 /gcd(d_1,d_2)\cdot d_2\),而不是\(d_1 \cdot d_2 / gcd(d_1,d_2)\),挂掉x4
  • 把除号放里面,不然有逆元,(其实是因为模了一个不该模的东西)挂掉x5

代码

#include <iostream>
#include <cstdio>
#include <algorithm> using namespace std; typedef long long ll; const int N = 1e5 + 10; ll n, x, y;
ll d[N], r[N]; ll mul(ll a, ll b, ll p){//龟速乘
int f = 1;
if(a < 0) f = -f, a = -a;
if(b < 0) f = -f, b = -b;
ll w = 0;
while(b){
if(b & 1)
w = (w + a) % p;
b >>= 1;
a = (a + a) % p;
}
return w * f;
} ll exgcd(ll a, ll b){//扩欧
ll ans, t;
if(b == 0){
x = 1;
y = 0;
return a;
} else {
ans = exgcd(b, a % b);
t = x;
x = y;
y = t - a / b * y;
} return ans;
} ll exCRT(){ for(int i = 2; i <= n; ++i){
ll C = r[1] - r[i];
ll D = exgcd(d[i], d[1]);
if(C % D) return -1;
ll k1 = mul(y , c / D, d[1] / D * d[i] );
ll x0 = mul(-k1 , d[1], d[1] / D * d[i] ) + r[1];
d[1] = d[1] / D * d[i], r[1] = x0;
r[1] = (r[1] % d[1] + d[1]) % d[1];//先模一遍,让绝对值小于,然后处理
}
return r[1];
} int main(){
scanf("%lld", &n);
for(int i = 1; i <= n; ++i){
scanf("%lld %lld", &d[i], &r[i]);
}
long long ans = exCRT();
printf("%lld", ans);
return 0;
}

我知道写的超级丑,比不上fym

[笔记] CRT & exCRT的更多相关文章

  1. CRT & EXCRT 学习笔记

    这玩意解决的是把同余方程组合并的问题. CRT的核心思想和拉格朗日插值差不多,就是构造一组\(R_i\)使得$\forall i,j(i \neq j) $ \[R_im_i = 1, R_im_j ...

  2. CRT&EXCRT学习笔记

    非扩展 用于求解线性同余方程组 ,其中模数两两互质 . 先来看一看两个显然的定理: 1.若 x \(\equiv\) 0 (mod p) 且 y \(\equiv\) 0 (mod p) ,则有 x+ ...

  3. CRT&EXCRT 中国剩余定理及其扩展

    前言: 中国剩余定理又名孙子定理.因孙子二字歧义,常以段子形式广泛流传. 中国剩余定理并不是很好理解,我也理解了很多次. CRT 中国剩余定理 中国剩余定理,就是一个解同余方程组的算法. 求满足n个条 ...

  4. CRT && exCRT模板

    CRT从各种方面上都吊打exCRT啊...... 短,好理解... 考虑构造bi使得bi % pi = ai,bi % pj = 0.然后全加起来就行了. 显然bi的构造就是ai * (P/pi) * ...

  5. crt,excrt学习总结

    \(crt,Chinese\ Remainder\ Theorem\) 概述 前置技能:同余基础性质,\(exgcd\). \(crt\),中国剩余定理.用于解决模数互质的线性同余方程组.大概长这样: ...

  6. [note]CRT&exCRT

    中国剩余定理 别人的blog 假设现在有关于x的同余方程组(p1,p2均为质数) \(x=a_1\pmod {p_1}\) \(x=a_2\pmod {p_2}\) 可以转化成如下形式 \(x=a_1 ...

  7. BZOJ 3782: 上学路 Lucas+ExCRT+容斥+dp

    其实呢,扩展中国剩余定理还有一种理解方式:就是你有一坨东西,形如:$A[i]\equiv B[i](mod$ $P[i])$. 对于这个东西,你可以这么思考:如果最后能求出一个解,那么这个解的增量一定 ...

  8. BZOJ 1951: [Sdoi2010]古代猪文 ExCRT+欧拉定理+Lucas

    欧拉定理不要忘记!! #include <bits/stdc++.h> #define N 100000 #define ll long long #define ull unsigned ...

  9. NOIp2018停课刷题记录

    Preface 老叶说了高中停课但是初中不停的消息后我就为争取民主献出一份力量 其实就是和老师申请了下让我们HW的三个人听课结果真停了 那么还是珍惜这次机会好好提升下自己吧不然就\(AFO\)了 Li ...

随机推荐

  1. 这些不可不知的JVM知识,我都用思维导图整理好了

    JVM是面试中必问的部分,本文通过思维导图以面向面试的角度整理JVM中不可不知的知识. 先上图: 1.JVM基本概念 1.1.JVM是什么 JVM 的全称是 「Java Virtual Machine ...

  2. Windows 10 Emoji shortcuts

    Windows 10 Emoji shortcuts Windows 10 Emoji 快捷方式 https://support.microsoft.com/en-us/windows/windows ...

  3. npm & config settings

    npm & config settings how to check npm config settings https://docs.npmjs.com/cli/config $ npm c ...

  4. iPad Pro 如何通过 USB-C 接口外接机械键盘

    iPad Pro 如何通过 USB-C 接口外接机械键盘 外接机械键盘 Type-C Dock OK,cnblogs 图片文件不能超过20M https://support.apple.com/zh- ...

  5. 「NGK每日快讯」2021.2.7日NGK公链第96期官方快讯!

  6. Codeforces 1485F Copy or Prefix Sum

    题目链接 点我跳转 题目大意 给定一个长度为 \(N\) 的序列 \(bi\) 问有多少个长度为 \(N\) 的序列 \(a\) 使得 \(b[i] = a[i]\) 或 \(b[i] = ∑a[j] ...

  7. python的with用法(转载)

    原文地址:https://www.cnblogs.com/wanglei-xiaoshitou1/p/9238275.html 一.with语句是什么? 有一些任务,可能事先需要设置,事后做清理工作. ...

  8. mysql一张表到底能存多少数据?

    前言 程序员平时和mysql打交道一定不少,可以说每天都有接触到,但是mysql一张表到底能存多少数据呢?计算根据是什么呢?接下来咱们逐一探讨 知识准备 数据页 在操作系统中,我们知道为了跟磁盘交互, ...

  9. Github Action 快速上手指南

    前言 各位读者,新年快乐,我是过了年匆忙赶回上海努力搬砖的蛮三刀. Github之前更新了一个Action功能(应该是很久以前了),可以实现很多自动化操作.用来替代用户自己设置的自动化脚本(比如:钩子 ...

  10. 17_MySQL分组查询的应用

    本节涉及SQL语句: -- 分组查询 SELECT deptno,AVG(sal) FROM t_emp GROUP BY deptno; -- 四舍五入 SELECT deptno,ROUND(AV ...