UVALive 4119 Always an integer——数学归纳法+小模拟

版权声明:欢迎大家转载,转载请注明出处 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;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/82468975