解模意义下的方程
可以视为解不定方程
A1∗x1+A2∗x2+A3∗x3+……+An∗xn+P∗xn+1=B
用欧几里得扩展算法
二元情形:
设
a>b。
1,显然当
b=0
时,
gcd(a,b)=a
。此时
x=1
,
y=0
;
2,
a
,
设
b∗x2+(a
mod
b)∗y2=gcd(b,a
mod
b)
根据朴素的欧几里德原理有
gcd(a,b)=gcd(b,amodb)
则:
a∗x1+b∗y1=b∗x2+(a
mod
b)∗y2
即:
a∗x1+b∗y1=b∗x2+(a−[a/b]∗b)∗y2=a∗y2+b∗x2−[a/b]∗b∗y2
也就是 a∗x1+b∗y1==a∗y2+b∗(x2−[a/b]∗y2)
根据恒等定理得:
x1=y2
,
y1=x2−[a/b]∗y2
;
这样我们就得到了求解
x1,y1
的方法:
x1,y1
的值基于
x2,y2
.
多元情形:
gcd(a1,a2,……,ai−1)∗x+ai∗y=gcd(a1,a2,……,ai−1,ai)
可以用二元方法解出
x,y
原方程中
Xi=y,Xj=Xj∗x,j<i
最后要注意把 X <script type="math/tex" id="MathJax-Element-6426">X</script>都变成非负整数
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
const int MAXN = 105;
int ax[MAXN] = {0};
int A[MAXN] = {0};
int N,P,B;
int super_gcd(int a,int b,int &x,int &y)
{
if(!b)
{
x = 1;
y = 0;
return a;
}
else
{
int ret = super_gcd(b,a%b,x,y);
int tmp = x;
x = y;
y = tmp - a/b*y;
return ret;
}
}
int main()
{
int gcd;
#ifndef ONLINE_JUDGE
freopen("sgu140.in","r",stdin);
freopen("sgu140.out","w",stdout);
#endif
scanf("%d%d%d",&N,&P,&B);
for(int i = 1; i <= N; i++)
{scanf("%d",&A[i]);A[i] %= P;}
ax[1] = 1 , gcd = A[1]; A[N+1] = P;
for(int i = 2; i <= N+1; i++)
{
int x , y;
gcd = super_gcd(gcd , A[i] , x , y);
ax[i] = y;
for(int j = 1 ; j < i; j++)
ax[j] *= x,ax[j] %= P;
}
if(B%gcd)
puts("NO");
else
{
int tmp = B/gcd;
for(int i = 1; i <= N; i++)
{ax[i] *= tmp; ax[i] = (ax[i]%P + P)%P;}
puts("YES");
for(int i = 1; i <= N; i++)
printf("%d ",ax[i]);
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
}