拓展中国剩余定理
模板原型:洛谷P4777
什么是拓展中国剩余定理
相信大家都听说过中国剩余定理 (其实没有听说过也没关系,因为拓展中国剩余定理与中国剩余定理其实没有什么关系) 。拓展中国剩余定理的大意是这样的:
给定n组非负整数ai,bi,求解关于x的方程组:
x ≡ b1(mod a1)
x ≡ b2(mod a2)
……
x ≡ bn(mod an)
的最小非负整数解
拓展中国剩余定理的基本思路
假设已有答案 ans,满足前k-1项条件。
设 M 为 a1 —a(k-1) 的最小公倍数,则 ans + x * M 一定满足ans + x * M ≡ b1—b(k-1) 。
假设 ans + x * M ≡ bk(mod ak),那么问题转化为求 n * M + m * ak = bk - ans 的最小正整数解。
但必须保证 bk - ans 为正数。
代码
#include<cstdio>
#define ll long long
using namespace std;
ll n,a,b,tot,M;
ll ans,x,y,r;
ll flag=1,mul;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;y=0;
return a;
}
ll d=exgcd(b,a%b,x,y);
ll t=y;
y=x-(a/b)*y;
x=t;
return d;
}//求解同余方程
ll quick_mul(ll nw,ll aim,ll mod)
{
ll res=0;
while(aim>0)
{
if(aim&1)res=(res+nw)%mod;
nw=(nw+nw)%mod;
aim>>=1;
}
return res;
}//龟速乘QAQ(模板)
int main()
{
scanf("%I64d",&n);
while(n--)
{
x=0;
y=0;
tot++;//tot计数
scanf("%I64d%I64d",&a,&b);
if(tot==1)
{
ans=b;
M=a;
continue;
}//初始化
r=exgcd(M,a,x,y);//求最大公因数
mul=((b-ans)%a+a)%a;
x=quick_mul(x,mul/r,a);
if((b-ans)%r!=0)
{
flag=0;
continue;
}//判断无解
ans=ans+(x*M);
M=(M*a)/r;//更新最小公倍数
ans=(ans%M+M)%M;//保证ans为正值
}
if(flag)
printf("%I64d",ans);
else
printf("No");
return 0;
}
但是我这个代码过不了洛谷模板的最后三个点,各位大神如果有更好的思路希望在下面评论哦!~~~