zoukankan      html  css  js  c++  java
  • 数论学习笔记

    扩展欧几里得(exgcd)

    模板先打上

    void exgcd(ll a,ll b)
    {
    	if(!b)
    	{
    		x1=1;y1=0;return;
    	}
    	exgcd(b,a%b);
    	ll t=x1;
    	x1=y1;y1=t-a/b*y1;
    }
    

    扩欧一般用来求解形如 (ax+by=gcd(a,b)) 的不定方程,同时也可以用于求乘法逆元,这之后再讲。

    一般来说,通过上述函数求出来的只是一组特解,很多情况下并不是我们需要的答案,所以还要对其进行处理。大多数情况下,题目都会要求我们求 (x) 的最小正整数解,此时 (x) 一般等于 ((x\%p+p)\%p) ,这就是 (x) 的最小正整数解。

    最简单的一道例题:P1082 同余方程

    再来看更难的模板题:P5656 【模板】二元一次不定方程(exgcd)

    这里要求的是 (ax+by=c) 的解,要求很多,我们一个一个来看。首先判无解的情况,这里我设 (d=gcd(a,b)),可以发现,如果 (d mid c) ,那么这个方程就没有整数解。

    为什么呢?可以证明,因为题中 (x,y) 均为整数,且 (a)(b) 一定是 (d) 的倍数,所以 (ax+by) 也一定是 (d) 的倍数,又因为 (c=ax+by) ,所以 (c\%d=0) 可以得证。

    因此,若 (d mid c) ,则方程无整数解。

    若有整数解,我们可以设 (a'=a/d,b'=b/d,c'=c/d) , 并用 (exgcd) 求出 (a'x_0+b'y_0=1) 的一组整数解 (x_0,y_0) ,则 (a'c'x_0+b'c'y_0=c') ,两边再同乘 (d) ,就得到 (ac'x_0+bc'x_0=c) ,由此得到原方程的一组特解 (x_1=c'x_0,y_1=c'y_0)

    此时我们可以先把 (x) 的最小正整数解算出来,即 (x_{min}=(x\%b+b)\%b) ,要注意的是若 (x\%b=0) ,则 (x_{min}=b)

    观察方程可知,当 (x) 越小时,(y) 越大,所以此时与 (x_{min}) 对应的那个 (y) 即为 (y) 的最大正整数解。因为 (a'x_{min}+b'y_{max}=c') ,所以 (y_{max}=frac{c'-a'x_{min}}{b'})

    若此时的 (y_{max}>0) ,则说明有正整数解,于是可以同理求出 (x_{max})(y_{min}) ,然后因为 (x_{min})(x_{max}) 之间每隔 (b') 个数就有一个解,所以正整数解的个数为 ((x_{max}-x_{min})/b'+1)

    若此时 (y_{max}le 0) ,则说明没有正整数解,同理计算出 (y_{min}) 即可。

    习题

    1.P1516 青蛙的约会

    2.P2613 【模板】有理数取余

    乘法逆元

    定义:对于形如 (axequiv 1pmod b) 的同余方程,此时 (x) 的最小正整数解即为 (a) 的逆元。

    是不是感觉有些熟悉?没错,这和我们上面的例题P1082一模一样。可以将其化为 (ax+by=1) 的不定方程,并使用扩欧求解。

    但求逆元不只能用扩欧,还可以用费马小定理+快速幂,但是博主不会,所以等以后再讲。

    模板题:P3811 【模板】乘法逆元

    除了上述两种方法,还有一种 (O(n)) 求逆元的递推方法。这里给出公式,先设 (inv(i))(i) 在模 (p) 意义下的逆元,则 (inv(i)=(ll)p-p/i*inv(p\%i)\%p) ,初始条件为 (inv(1)=1,inv(0)=0)

    如果要求某一个数模 (p) 的逆元,可以使用此公式递归求解,证明请见模板题解。

    中国剩余定理(CRT)

    中国剩余定理是用于求解形如

    [egin{cases}xequiv a_1pmod {m_1}\xequiv a_2pmod {m_2}\ldots\xequiv a_kpmod {m_k}end{cases} ]

    同余方程组的定理,其中 (m_1,m_2,ldots,m_k) 为两两互质的整数,要求找出 (x) 的最小非负整数解。

    求解过程

    首先设 (M)(prod_{i=1}^km_i)(M_i=frac{M}{m_i}), (M_it_iequiv 1pmod {m_i})

    可以看出来 (t_i) 即为 (M_i) 的逆元,可以构造出一个解 (x_0=sum_{i=1}^ka_iM_it_i) ,我们要求的答案 (x) 即为 (x_0\%M)

    证明请看题解,搞不搞懂无所谓谁叫信息学只看答案呢

    模板题:P1495 【模板】中国剩余定理(CRT)/曹冲养猪

    主要部分代码

    void exgcd(ll a,ll b,int i)
    {
    	if(!b)
    	{
    		x[i]=1;y[i]=0;return;
    	}
    	exgcd(b,a%b,i);
    	ll t=x[i];
    	x[i]=y[i];y[i]=t-a/b*y[i];
    }
    int main()
    {
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld%lld",&a[i],&b[i]);
    		M*=a[i];
    	}
    	for(int i=1;i<=n;i++)
    	m[i]=M/a[i];
    	for(int i=1;i<=n;i++)
    	{
    		exgcd(m[i],a[i],i);
    		X+=b[i]*m[i]*(x[i]<0?x[i]+a[i]:x[i]);
    	}
    	printf("%lld",X%M);
    	return 0;
    }
    
  • 相关阅读:
    C语言 exit 函数 C语言零基础入门教程
    C/C++ getchar函数 C语言零基础入门教程
    自己动手重新实现LINQ to Objects: 7 Count和LongCount
    自己动手重新实现LINQ to Objects: 5 Empty
    自己动手重新实现LINQ to Objects: 8 Concat
    自己动手重新实现LINQ to Objects: 11 First,Last,Single以及它们带有OrDefault的重载
    自己动手重新实现LINQ to Objects: 3 Select
    自己动手重新实现LINQ to Objects: 2 Where
    自己动手重新实现LINQ to Objects: 10 Any和All
    用豆瓣读书Chrome插件,简单购买电子书
  • 原文地址:https://www.cnblogs.com/luotao0034/p/14038940.html
Copyright © 2011-2022 走看看