问题描述:给出bi,ni的值,且n1, n2, n3,…, ni两两之间不一定互质,求Res的值?
解:采用的是合并方程的做法。
这里将以合并第一第二个方程为例进行说明
由上图前2个方程得(设k1、k2为某一整数):
POJ 2891 求方程组最小解
//解一元线性同余方程组。
#include
#include
using namespace std;
typedef long long ll;
ll ex_gcd(ll a,ll b,ll& x,ll& y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll r,tx,ty;
r=ex_gcd(b,a%b,tx,ty);
x=ty;
y=tx-a/b*ty;
return r;
}
int main()
{
ll i,n,a1,r1,a2,r2,ans,a,b,c,d,x0,y0;
while(scanf("%lld",&n)!=EOF){
bool flag = 1;
scanf("%lld%lld",&a1,&r1);
for( i=1;iscanf("%lld%lld",&a2,&r2);
a = a1;
b = a2;
c = r2-r1;
ll d = ex_gcd(a,b,x0,y0);
if(c%d!=0){
flag = 0;
}
int t = b/d;
printf("%lld\n",d);
printf("%lld\n",x0);
x0 = (x0*(c/d)%t+t)%t;//保证x0为正
r1 = a1*x0 + r1;
a1 = a1*(a2/d);
}
if(!flag){
puts("-1");
continue;
}
printf("%lld\n",r1);
}
return 0;
}
关于方程的通解:
这里所求的解小于LCM(b数组所有元素)且非负数,即最小非负整数解。设b数组所有元素的最小公倍数为LCM,最小非负整数解为X0,则通解:X=x0+LCM*k,其中k为整数。
HDU 1573 求解的大小小于N的解的个数
//解一元线性同余方程组。
//解的个数
#include
#include
using namespace std;
typedef long long ll;
ll ex_gcd(ll a,ll b,ll& x,ll& y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll r,tx,ty;
r=ex_gcd(b,a%b,tx,ty);
x=ty;
y=tx-a/b*ty;
return r;
}
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
const int maxn=15;
int aa[maxn],rr[maxn];
int main()
{
ll n,m,a,b,c,d,x,y,lcm;
int casei;
cin>>casei;
while(casei--)
{
cin>>n>>m;
bool flag=1;
ll lcm=1;
for(int i=0;icin>>aa[i];
lcm=lcm/gcd(lcm,aa[i])*aa[i];
}
for(int i=0;icin>>rr[i];
for(int i=1;i0],b=aa[i],c=rr[i]-rr[0];
d=ex_gcd(a,b,x,y);
if(c%d)
{
flag=0;
break;
}
b/=d;
x=(x*(c/d)%b+b)%b;
rr[0]=aa[0]*x+rr[0];
aa[0]=aa[0]*(aa[i]/d);
}
if(!flag)
{
printf("0\n");
continue;
}
ll ans=0;
if(rr[0]<=n)
ans=1+(n-rr[0])/lcm;
if(ans&&rr[0]==0)
ans--;
cout<return 0;
}
HDU 3579 最小正整数解
//解一元线性同余方程组。
#include
#include
using namespace std;
typedef long long ll;
ll ex_gcd(ll a,ll b,ll& x,ll& y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll r,tx,ty;
r=ex_gcd(b,a%b,tx,ty);
x=ty;
y=tx-a/b*ty;
return r;
}
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
const int maxn=15;
ll aa[maxn],rr[maxn];
int main()
{
ll n,m,a,b,c,d,x,y,lcm;
int casei;
cin>>casei;
int ff=1;
while(casei--)
{
cin>>m;
bool flag=1;
ll lcm=1;
for(int i=0;icin>>aa[i];
lcm=lcm/gcd(lcm,aa[i])*aa[i];
}
for(int i=0;icin>>rr[i];
for(int i=1;i0],b=aa[i],c=rr[i]-rr[0];
d=ex_gcd(a,b,x,y);
if(c%d)
{
flag=0;
break;
}
b/=d;
x=(x*(c/d)%b+b)%b;
rr[0]=aa[0]*x+rr[0];
aa[0]=aa[0]*(aa[i]/d);
}
printf("Case %d: ",ff++);
if(!flag)
{
printf("-1\n");
continue;
}
if(rr[0])
printf("%lld\n",rr[0]);
else
printf("%lld\n",lcm);
}
return 0;
}