sgu140:Integer Sequences

140. Integer Sequences

time limit per test: 0.25 sec. 
memory limit per test: 4096 KB

A sequence A is called an integer sequence of length if all its elements A1 A2 .. AN are non-negative integers less than 2 000 000 000. Consider two integer sequences of length NA and X. The result of their multiplication (A*X) is an integer number R=A1*X1 + A2*X2 + .. + AN*XN. Your task is to solve the equation A*X=B (mod P), given the integer sequence A and the integer numbers Band P.

Input

The first line contains the integer numbers N (1<=N<=100) - the length of the integer sequences - P (1<=P<=10 000) and B (0<=B<=P-1). The second line contains the elements of the sequence A, separated by blanks: A1 A2 .. AN.

Output

You should print one line containing the word "YES" if there exists at least one integer sequence X which is a solution to the equation, or print "NO" otherwise. If the answer is "YES", the next line should contain N non-negative integers separated by blanks: X1 X2 .. XN.

Sample Input #1

2 7 4
7 3

Sample Output #1

YES
0 6

Sample Input #2

3 10 1
2 4 6

Sample Output #2

NO
一道扩展欧几里得的题,开始DP还想了一会,结果发现还是道数学题。
由于有mod P,为了方便,可以表示为A1X1+A2X2+A3X3+...+AnXn+P*Q=B,Q∈Z。
对于A1X1+A2X2,我们可以求出A1X1+A2X2=gcd(A1,A2)的X1、X2,存入X数组中,再把gcd(A1,A2)当作新的元素,于是方程变为:
k*gcd(A1,A2)+A3X3+...+An*Xn+P*Q=B,我们再对gcd(A1,A2),A3同样进行上述操作,求出k、X3,把之前求出的所有的Xi乘上k,再将X3加入X数组中,不断重复,直到算到An为止。
再把gcd(A1,A2,A3...An)与P进行同样的操作,同时把所有解乘上B/gcd(A1,A2...An,P),如果除不尽无解,否则输出,记得取模。
#include <cstdio>
using namespace std;
const int MAXN = 105, MAXP = 10005;
int N = 0, P = 0, B = 0;
int A[MAXN] = {0}, X[MAXN] = {0};

int ext(int a, int b, int &x, int &y)
{
  while(!b)
  {
    x = 1;
    y = 0;
    return a;
  }
  int re = ext(b, a%b, x, y);
  int tmp = x;
  x = y;
  y = tmp-a/b*y;
  return re;
}
int main()
{
  scanf("%d%d%d", &N ,&P, &B);
  for(int i = 1; i <= N; ++i)
  {
    scanf("%d", A+i);	
    A[i] %= P;
  }

  int a, b, gcd = A[1];
  X[1] = 1;
  for(int i = 2; i <= N; ++i)
  {
	gcd = ext(gcd, A[i], a, b);
	for(int j = 1; j < i; ++j) X[j] = X[j]*a%P;
	X[i] = b;
  }
  gcd = ext(gcd, P, a, b);
  if(B%gcd != 0)
  {
    puts("NO");
    return 0;
  }
  puts("YES");
  for(int i = 1; i <= N; ++i) X[i] = X[i]*a*B/gcd%P;
  printf("%d", (X[1]+P*100000)%P);
  for(int i = 2; i <= N; ++i) printf(" %d", (X[i]+P*100000)%P);
  return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值