poj 3471 整除与剩余

47 篇文章 0 订阅
2 篇文章 0 订阅

给出一个多项式 f(x)=x^n+An-1*x^(n-1)+.....+A0  求其所有零点(包括)重根, 由韦达定理的扩展我们知道所有的整数零点的绝对值都是A0的约数,可以枚举约数,然后计算f(x)/(x-a)

a为当前枚举的约数,判断是否整除,如果A0=0,则我们令f(x) ,中每一项均除以x,直到常数项不为0,然后对常数项的绝对值进行质因子分解然后求取所有因数 

  f(x)=(x-x1)*(x-x2)*(x-x3)*(x-x4)******(x-xm)*g(x)

依托多项式除法此问即可求解

/*
ID: BryatnMark
LANG: JAVA
TASK: AC
 */
import java.util.*;
import java.io.*;
import java.math.*;
import java.util.*;

public class Main {
	public static void main(String args[]) throws Exception {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Task solver = new Task();
		solver.main(in, out);
		out.close();
	}
}

class InputReader {
	BufferedReader reader;
	StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		tokenizer = null;
	}

	public String next() {
		if (!hasNext())
			throw new RuntimeException();
		return tokenizer.nextToken();
	}

	boolean hasNext() {
		while (tokenizer == null || !tokenizer.hasMoreTokens())
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (Exception e) {
				return false;
			}
		return true;
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public BigInteger nextBigInteger() {
		return new BigInteger(next());
	}
}

class Task {
	final int SIZE = 100000;
	final int maxn = 111;
	final int TSIZE = 2111;
	BigInteger zero = BigInteger.ZERO;
	BigInteger one = BigInteger.ONE;
	BigInteger[] a = new BigInteger[maxn];
	BigInteger[] b = new BigInteger[maxn];
	long[] p = new long[SIZE];
	boolean[] vis = new boolean[SIZE + 100];

	long[] co = new long[TSIZE];
	int[] c = new int[TSIZE];
	long[] f = new long[TSIZE];
	long[] divisor = new long[TSIZE];
	long[] ans = new long[TSIZE];

	int cnt = 0;
	int size = 0;
	int tot = 0;
	int num = 0;

	void spilt(long a) {
		cnt = 0;
		int i;
		Arrays.fill(c, 0);
		for (i = 0; p[i] * p[i] <= a && i < size; ++i) {
			if (a % p[i] == 0) {
				f[cnt] = p[i];
				while (a % p[i] == 0) {
					a /= p[i];
					c[cnt]++;
				}
				++cnt;
			}
		}
		if (a > 1) {
			c[cnt]++;
			f[cnt] = a;
			++cnt;
		}
	}

	void dfs(int k, long d) {
		if (k >= cnt) {
			divisor[num++] = d;
			return;
		}
		for (int i = 0; i <= c[k]; d *= f[k], ++i) {
			dfs(k + 1, d);
		}
	}

	void reverse(long[] a, int n) {
		long t;
		int i = 0, j = n;
		while (i < j) {
			t = a[i];
			a[i] = a[j];
			a[j] = t;
			++i;
			--j;
		}
		// for(i=0;i<=n;++i) System.out.print(a[i]+" ");
		// System.out.println();
	}

	boolean ok(long A, int n) {
		BigInteger t = BigInteger.valueOf(A);
		int i;
		for (i = 0; i <= n; ++i)
			b[i] = a[i];
		for (i = n; i >= 1; --i) {
			b[i - 1] = b[i - 1].add(t.multiply(b[i]));
		}

		return b[0].equals(zero);
	}

	void main(InputReader in, PrintWriter out) throws Exception {
		int n, i, j;
		size = 0;
		vis[0] = vis[1] = true;
		for (i = 2; i * i <= SIZE; ++i)
			if (!vis[i])
				for (j = i * i; j <= SIZE; vis[j] = true, j += i)
					;
		for (i = 2; i <= SIZE; ++i)
			if (!vis[i])
				p[size++] = i;

		for (i = 0; i < maxn; ++i)
			a[i] = b[i] = zero;
		while (in.hasNext()) {
			n = in.nextInt();
			co[0] = 1;
			tot = num = 0;
			for (i = 1; i <= n; ++i) {
				co[i] = in.nextLong();
			}
			while (n > 0 && co[n] == 0) {
				ans[tot++] = co[n];
				--n;
			}
			reverse(co, n);
			spilt(Math.abs(co[0]));
			dfs(0, 1);
			for (i = 0; i <= n; ++i)
				a[i] = BigInteger.valueOf(co[i]);
			for (i = 0; i < num && n > 0; ++i) {
				while (ok(divisor[i], n) && n > 0) {
					ans[tot++] = divisor[i];
					for (j = 0; j < n; ++j)
						a[j] = b[j + 1];
					--n;
				}
				while (ok(-divisor[i], n) && n > 0) {
					ans[tot++] = -divisor[i];
					for (j = 0; j < n; ++j)
						a[j] = b[j + 1];
					--n;
				}
			}
			out.println(tot);
			Arrays.sort(ans, 0, tot);
			for (i = 0; i < tot; ++i) {
				out.println(ans[i]);
			}

		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值