版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/82468975
首先开个结构体把每个C和E以及最后那个D膜出来
然后算出E的最大值k,将数值1~k+1带入n验证,全部正确则Always an integer,否则Not always an integer
下面证明一下为什么只验证1~k+1就可以,我们用数学归纳法进行验证:
当k=0时,式子中没有变量,可以将n视为1来验证式子
当k=1时,整个式子为n的一次函数,可设f(n) = an+b,则f(n+1) - f(n) = a,显然f(n)是首项为f(1),公差为f(2)-f(1)的等差数列,则只要首项和公差为D的倍数就Always an integer,顾只验证f(1)和f(2)即可
当k=2时,同理可写出f(n+1)-f(n) = 2an+a+b,只要首项和公差都为D的倍数就可以Always an integer,但我们如何验证2an+a+b是D的倍数呢?类比k=1的情况,我们可以带入3,然后f(3) - f(2)再构造出一个差值,然后用k=1的方法验证这两个差值是否合法即可。
上述三种情况本质上是一阶差分数列、二阶差分数列的应用,由此推下去可证明k=m -> k=m+1成立,故这个定理是正确的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int ks;
char s[maxn];
int cnt;
struct Node {
ll C, E;
}node[maxn];
ll D;
void init() {
int n = strlen(s);
cnt = 0;
int i = 1;
while (s[i] != ')') {
//C:
ll C = 0;
ll flag = 1;
if (s[i] == '+') flag = 1, i++;
else if (s[i] == '-') flag = -1, i++;
if (isdigit(s[i])) {
C = 0;
while (isdigit(s[i])) C = C * 10 + s[i++] - '0';
}
else {
C = 1;
}
C *= flag;
//E
ll E = 0;
if (s[i] == 'n') {
i++;
if (s[i] == '^') {
i++;
E = 0;
while (isdigit(s[i])) E = E * 10 + s[i++] - '0';
}
else {
E = 1;
}
}
else {
E = 0;
}
++cnt;
node[cnt].C = C, node[cnt].E = E;
}
i += 2;
D = 0;
for (;i < n; i++) D = D * 10 + s[i] - '0';
// for (int i = 1; i <= cnt; i++) {
// if (i != 1) cout << "+";
// cout << "(" << node[i].C << "n^" << node[i].E << ")";
// }
// cout << "/" << D << endl;
}
ll ipow(ll x, ll y) {
ll ans = 1;
while (y) {
if (y & 1) ans = ans * x % D;
x = x * x % D;
y >>= 1;
}
return ans;
}
bool judge() {
ll k = 0;
for (int i = 1; i <= cnt; i++) k = max(k, node[i].E);
if (k == 0) {
ll sum = 0;
for (int i = 1; i <= cnt; i++) sum += node[i].C;
return sum % D == 0;
}
for (int i = 1; i <= k + 1; i++) {
ll sum = 0;
for (int j = 1; j <= cnt; j++) {
sum = (sum + node[j].C * ipow(i, node[j].E) % D + D) % D;
}
if (sum % D != 0) return false;
}
return true;
}
int main() {
while (~scanf("%s", &s) && s[0] != '.') {
init();
if (judge()) printf("Case %d: Always an integer\n", ++ks);
else printf("Case %d: Not always an integer\n", ++ks);
}
return 0;
}