zoukankan      html  css  js  c++  java
  • 中国剩余定理及拓展

    我好菜啊

    中国剩余定理

    我愿意称它为动动定理

    有方程组:

    [egin{cases}xequiv a_1 (mod p_1)\xequiv a_2 (mod p_2)\……\xequiv a_n (mod p_n)end{cases} ]

    其中对于(iin[1,n],p_i)两两互质

    求解:

    定义(M=prodlimits_{i=1}^{n}p_i,M_i=frac{prodlimits_{j=1}^{n}p_j}{p_i})

    则方程组的解为(sumlimits_{i=1}^{n}a_i*M_i*p_i^{-1})

    证明:

    观察(a_i*M_i*p_i^{-1})

    对于(j e i)来说,由于(M_i)(p_j)的倍数,所以(equiv 0(mod p_j))

    对于(i)来说,由于(p_i)两两互质,所以(M_i)中不含(p_i)的倍数,且(a_i*M_i*p_i^{-1}equiv a_i(mod p_i))

    code

    给我也整一个

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define int long long
    #define eps (1e-8)
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=110;
    	int n,m=1,x,y,ret;
    	int a[N],p[N];
    	inline void exgcd(int &x,int &y,int a,int b)
    	{
    		if(!b){x=1,y=0;return;}
    		exgcd(y,x,b,a%b);
    		y-=a/b*x;
    	}
    	inline void crt()
    	{
    		for(int i=1;i<=n;++i)
    		{
    			exgcd(x,y,m/p[i],p[i]);
    			ret=(ret+m/p[i]*x%m*a[i]%m)%m;
    		}
    	}
    	inline void main()
    	{
    		n=read();
    		for(int i=1;i<=n;++i)
    		{
    			p[i]=read();
    			a[i]=read()%p[i];
    			m*=p[i];
    		}
    		crt();
    		printf("%lld
    ",(ret%m+m)%m);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    

    拓展中国剩余定理

    有方程组:

    [egin{cases}xequiv a_1 (mod p_1)\xequiv a_2 (mod p_2)\……\xequiv a_n (mod p_n)end{cases} ]

    还是它!不过我们这次不保证(p_i)两两互质

    我们选择关闭本题

    求解:

    其实我们可以数学归纳,假设我们已经求解出了前(k-1)个方程组的答案

    重新定义(M=LCM_{i=1}^{k-1}p_i),则前(k-1)个方程的解为(x+i*M(iin Z))

    考虑与第(k)个方程合并,使得(x+t*Mequiv a_k(mod p_k))

    去掉模数+移项得到(t*M+y*p_kequiv a_k-x)

    我们用(exgcd)求出(t),则前(k)个方程组的解为(x+t*M)

    注意(exgcd)无解的情况

    code

    给我再整一个

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define int long long
    #define eps (1e-8)
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=1e5+10;
    	int n,m,ret;
    	int a[N],p[N];
    	int x,y,g;
    	inline void exgcd(int &x,int &y,int &g,int a,int b)
    	{
    		if(!b){x=1,y=0,g=a;return;}
    		exgcd(y,x,g,b,a%b);
    		y-=a/b*x;
    	}
    	inline int slow(int x,int k,int p)
    	{
    		int ret=0;
    		while(k)
    		{
    			if(k&1) ret=(ret+x)%p;
    			x=(x+x)%p;
    			k>>=1;
    		}
    		return ret;
    	}
    	inline void excrt()
    	{
    		m=p[1],ret=a[1];
    		for(int i=2;i<=n;++i)
    		{
    			int c=((a[i]-ret)%p[i]+p[i])%p[i];
    			exgcd(x,y,g,m,p[i]);
    			if(c%g);//无解
    			x=slow(x,c/g,p[i]);
    			ret+=x*m;
    			m*=p[i]/g;
    			ret=(ret+m)%m;
    		}
    	}
    	inline void main()
    	{
    		n=read();
    		for(int i=1;i<=n;++i) p[i]=read(),a[i]=read()%p[i];
    		excrt();
    		printf("%lld
    ",(ret%m+m)%m);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    
  • 相关阅读:
    iphoneX适配
    是时候啃一啃http跟https了
    使用阿里巴巴矢量图标库的图标
    react使用高阶组件进行界面跳转
    js性能提升之函数的防抖和节流
    vuex的一些需要知道的点
    react项目之使用猪齿鱼框架---dataSet的基础使用
    从js下手提升代码性能
    vue+ts搭建工程
    学习笔记之TypeScript语法一
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12058053.html
Copyright © 2011-2022 走看看