题目链接:https://cn.vjudge.net/problem/UVA-1069
题意:给出一个多项式(P) / D,P = Am * n^m + Am-1 * n^(m-1) + ... + A2 * n^2 + A1 * n + A0, 判断是否对于所有的正整数,其结果都为整数
思路:判断对于所有的正整数,(P) / D 的结果是否都为整数,等价于判断对于所有的正整数,(P) mod D == 0是否恒成立.
题目中给的m(幂)最大为100,可以用试验法来判断(P) / D 的整数性。
只需判断n = 1, 2, 3, ..., m, m + 1时,(P) / D 是否都为整数即可,若都为整数,则对于所有的正整数,(P) / D的结果都为整数,用数学归纳法证明如下:
m = 1时,P(n) = A1*n + A0, 为等差数列, 首项与公差均为D的倍数时,则整个数列为D的倍数, 所以,验证P(1), P(2)即可
假设m = k时,P(n) = Ak * n^k + ... + A2 * n^2 + A1 * n + A0, 验证P(1), P(2), ..., P(k), P(k+1)即可
则m = k + 1时,
P(n) = Ak+1 * n^(k+1) + Ak * n^k + ... + A2 * n^2 + A1 * n + A0
P(n + 1) = Ak+1 * (n+1)^(k+1) + Ak * (n+1)^k + ... + A2 * (n+1)^2 + A1 * (n+1) + A0,
P(n+1) - P(n) = Ak+1 * ((n+1)^(k+1) - n^(k+1)) + Ak * ((n+1)^k - n^k) + ... + A2 * ((n+1)^2 - n^2) + A1 * ((n+1) - n) + A0
= Bk * (n+1)^k + Bk-1 * (n+1)^(k-1) + ... + B2 * (n+1)^2 + B1 * (n+1) + B0
验证 P(2) - P(1), P(3) - P(2), ..., P(k+1) - P(k), P(k+2) - P(k+1) 即可,
即验证 P(1), P(2), P(3), ..., P(k), P(K+1), P(K+2),
说明假设成立,证明完毕。
对输入的表达式进行解析,将多项式的每一项系数存起来,然后进行验证即可。
求多项式的值可用秦九韶算法,将复杂度从o(n^2)降到o(n)
代码:
# include
# include
# include
# include
using namespace std;
typedef long long ll;
const int maxn = 100 + 5;
char s[maxn * maxn];
int a[maxn];
int d;
int maxp;
void f() {
int len = strlen(s);
memset(a, 0, sizeof a);
int sum = 0; char fh = '+';
int ss = 0; maxp = 0;
for (int i = 1; i < len; ++i) {
if (isdigit(s[i])) sum = sum * 10 + s[i] - '0';
if (s[i] == 'n') {
if (sum == 0) sum = 1;
if (fh == '-') sum = -sum;
if (s[i + 1] != '^') { a[1] = sum; maxp = max(maxp, 1); }
else {
for (i += 2; isdigit(s[i]); ++i) ss = ss * 10 + s[i] - '0';
a[ss] = sum; maxp = max(maxp, ss);
}
sum = 0; fh = '+'; ss = 0;
} else if (s[i] == ')') {
if (fh == '-') sum = -sum;
a[0] = sum;
sum = 0; fh = '+'; ss = 0;
} else if (s[i] == '/') {
d = 0;
for (++i; i < len; ++i) d = d * 10 + s[i] - '0';
}
if (s[i] == '-') fh = '-';
}
}
bool judge(int x) {
int ys = a[maxp] % d;
for (int i = maxp - 1; i >= 0; --i) {
ys = ((ll)ys * x + a[i]) % d;
}
return ys == 0;
}
int main(void)
{
int Case = 0;
while (~scanf("%s", s)) {
if (strcmp(".", s) == 0) break;
f();
bool ok = true;
for (int i = 1; i <= maxp + 1; ++i) {
if (judge(i) == false) { ok = false; break; }
}
printf("Case %d: ", ++Case);
if (ok == true) printf("Always an integer\n");
else printf("Not always an integer\n");
}
return 0;
}
/*
(n^2-n)/2
(2n^3+3n^2+n)/6
(-n^14-11n+1)/3
(-2)/2
(-2)/1
(-2)/3
(n-1)/1
(n-1)/2
*/