In 2003 NOIP universal solution to a problem set rematch

The topics covered algorithm:

  • Table tennis: Simple string simulation;
  • Numbers game: the DP interval;
  • Stack: Number of Cattleya
  • Meissen number: precision, fast power, mathematics.

pingpong

Topic links: https://www.luogu.org/problem/P1042
This question is a more complicated string simulation, irritated but not difficult.
I thought to code input is 'E' until all stored into a string, and then traverse the string, to store the score with win_point win, to store the opponent by win lose_point score, if the condition is satisfied (win_point>=11 || lose_point>=11) && abs(win_point-lose-point)>=2, then inning ended (21-point scale empathy).
One thing to note here is: I need to finally output current sentence current score ( '0: 0' but also output).
Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
char s[1000000], c;
int n, win_point, lost_point;
int main() {
    while ((c = getchar()) != 'E') {
        if (c == 'W' || c == 'L') s[n++] = c;
    }
    for (int i = 0; i < n; i ++) {
        s[i] == 'W' ? win_point ++ : lost_point ++;
        if ((win_point >= 11 || lost_point >= 11) && abs(win_point-lost_point) >= 2) {
            cout << win_point << ":" << lost_point << endl;
            win_point = lost_point = 0;
        }
    }
    cout << win_point << ":" << lost_point << endl;
    cout << endl;
    win_point = lost_point = 0;
    for (int i = 0; i < n; i ++) {
        s[i] == 'W' ? win_point ++ : lost_point ++;
        if ((win_point >= 21 || lost_point >= 21) && abs(win_point-lost_point) >= 2) {
            cout << win_point << ":" << lost_point << endl;
            win_point = lost_point = 0;
        }
    }
    cout << win_point << ":" << lost_point << endl;
    return 0;
}

Numbers game

Topic links: https://www.luogu.org/problem/P1043
This question involves knowledge: interval DP.
It involves a ring, but we can open this ring.
We assume that the input is \ (A_1, \ DOTS, A_N \) , then we can

  • Order \ (sum [i] \) represents \ (a_1 + \ dots + a_i \)
  • Order \ (maxv [i] [j ] [k] \) representing the interval \ ([i, j] \ ) range into \ (K \) parts of the product of the maximum obtainable;
  • Order \ (maxv [i] [j ] [k] \) representing the interval \ ([i, j] \ ) range into \ (K \) Maximum product parts can be obtained

Can be obtained the state transition equation is as follows:
\ (MAXV [I] [J] [K] = max (MAXV [I] [J] [K], MAXV [I] [L] [K-. 1] * get_mod (SUM [ J] -sum [L])) \)
\ (MINV [I] [J] [K] = min (MINV [I] [J] [K], MINV [I] [L] [. 1-K] * get_mod (sum [j] -sum [ l])) \)

Wherein, \ (get_mod (A) \) for obtaining \ (a \ mod 10 \) results.

Then:
maximum value is \ (maxv [1] [n ] [m] \) and satisfies all conditions \ (maxv [i] [j ] [m-1] * get_mod (sum [i-1] + sum [ n] - [j]) \ ) sum maximum value; the
minimum value is \ (minv [1] [n ] [m] \) and satisfies all conditions \ (minv [i] [j ] [m-1 ] * get_mod (sum [i- 1] sum n] + [- sum [j]) \) the minimum value of.
This would solve the problem of the ring, the outermost ring because certainly the most only some.
Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 55;
int n, m, a[maxn], sum[maxn];
long long maxv[maxn][maxn][10], minv[maxn][maxn][10], max_ans, min_ans;
long long get_mod(long long a) {
    return (a % 10 + 10) % 10;
}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
        sum[i] = sum[i-1] + a[i];
    }
    if (m == 1) {
        cout << get_mod(sum[n]) << endl;
        cout << get_mod(sum[n]) << endl;
        return 0;
    }
    for (int k = 1; k <= m; k ++) {
        for (int i = 1; i+k-1 <= n; i ++) {
            for (int j = i+k-1; j <= n; j ++) {
                if (k == 1) {
                    maxv[i][j][k] = get_mod(sum[j] - sum[i-1]);
                    minv[i][j][k] = get_mod(sum[j] - sum[i-1]);
                }
                else { // k > 1
                    for (int l = i+k-2; l < j; l ++) {
                        maxv[i][j][k] = max(maxv[i][j][k], maxv[i][l][k-1] * get_mod(sum[j]-sum[l]) );
                        minv[i][j][k] = min(minv[i][j][k], minv[i][l][k-1] * get_mod(sum[j]-sum[l]) );
                    }
                }
            }
        }
    }
    max_ans = maxv[1][n][m];
    min_ans = minv[1][n][m];
    for (int i = 1; i <= n-m+1; i ++) {
        for (int j = i+m-2; j <= n; j ++) {
            max_ans = max(max_ans, maxv[i][j][m-1] * get_mod(sum[i-1] + sum[n] - sum[j]) );
            min_ans = min(max_ans, minv[i][j][m-1] * get_mod(sum[i-1] + sum[n] - sum[j]) );
        }
    }
    cout << min_ans << endl;
    cout << max_ans << endl;
    return 0;
}

Stack

Topic Description: https://www.luogu.org/problem/P1044
This question is a "Cattleya number of" directly set formula when I do (of course there recurrence formula), using the following formula:
\ (Ci is = \ frac1 {n + 1} C_ {
2n} ^ \) n codes are as follows:

#include <bits/stdc++.h>
using namespace std;
int n;
long long m1 = 1, m2 = 1, tmp;
int main() {
    cin >> n;
    for (int i = n; i >= 1; i --) {
        m1 *= i+n;
        m2 *= i;
        tmp = __gcd(m1, m2);
        m1 /= tmp;
        m2 /= tmp;
    }
    m1 /= n+1;
    cout << m1 << endl;
    return 0;
}

The number of wheat forest

Topic links: https://www.luogu.org/problem/P1045
This question is a glance + Quick high-precision power.
There is an optimization, that is, the length, P is the number of bits as binary, and it will not be continuous in all decimal \ (9 \) , so \ (2 ^ P-1 \ ) recognition and \ ( 2 ^ P \) have the same number of bits.
So the length of directly by the formula \ (\ lceil P \ times \ frac {\ log 2} {\ log 10} \ rceil \) is obtained.
Then the most violent rapid precision power is the power of time out, but if we factor in the operation to ensure that the process to offset no more than 500 (interception at the end of 500), it will not time out.
(Then I was older and so precision operational moved directly before I wrote the template embarrassing - so we still look like the main function, multithe function is high-precision multiply Subfunction is precision cut)
codes are as follows:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10000010;

int a[maxn], b[maxn], res[maxn];

string add(string s1, string s2) {  // under condition: s1,s2>=0
    // 初始化部分
    int n = s1.length(), m = s2.length();
    for (int i = 0; i < n; i ++) a[i] = s1[n-1-i] - '0';
    for (int i = 0; i < m; i ++) b[i] = s2[m-1-i] - '0';
    int len = max(n, m) + 1;
    for (int i = n; i < len; i ++) a[i] = 0;
    for (int i = m; i < len; i ++) b[i] = 0;
    for (int i = 0; i < len; i ++) res[i] = 0;
    // 处理部分
    for (int i = 0; i < len; i ++) {
        res[i] += a[i] + b[i];
        if (res[i] >= 10) {
            res[i+1] += res[i] / 10;
            res[i] %= 10;
        }
    }
    // 返回部分
    int i = len-1;
    while (res[i] == 0 && i > 0) i --;
    string s = "";
    for (; i >= 0; i --) {
        char c = (char) (res[i] + '0');
        s += c;
    }
    return s;
}

string sub(string s1, string s2) {  // under condition: s1>=s2>=0
    // 初始化部分
    int n = s1.length(), m = s2.length();
    for (int i = 0; i < n; i ++) a[i] = s1[n-1-i] - '0';
    for (int i = 0; i < m; i ++) b[i] = s2[m-1-i] - '0';
    int len = max(n, m);
    for (int i = n; i < len; i ++) a[i] = 0;
    for (int i = m; i < len; i ++) b[i] = 0;
    for (int i = 0; i < len; i ++) res[i] = 0;
    // 处理部分
    for (int i = 0; i < len; i ++) {
        res[i] += a[i] - b[i];
        if (res[i] < 0) {
            res[i+1] --;
            res[i] += 10;
        }
    }
    // 返回部分
    int i = len-1;
    while (res[i] == 0 && i > 0) i --;
    string s = "";
    for (; i >= 0; i --) {
        char c = (char) (res[i] + '0');
        s += c;
    }
    return s;
}

bool cmp(string s1, string s2) {    // under condition: s1,s2 >= 0
    int n = s1.length(), m = s2.length();
    int i;
    for (i = 0; i < n-1 && s1[i] == '0'; i ++);
    s1 = s1.substr(i);
    for (i = 0; i < m-1 && s2[i] == '0'; i ++);
    s2 = s2.substr(i);
    if (s1.length() != s2.length()) return s1.length() < s2.length();
    return s1 < s2;
}

string Add(string s1, string s2) {
    if (s1[0] == '-' && s2[0] == '-') {
        return "-" + add(s1.substr(1), s2.substr(1));
    }
    else if (s1[0] == '-') {
        s1 = s1.substr(1);
        if (cmp(s1, s2) == true) {
            return sub(s2, s1);
        } else {
            return "-" + sub(s1, s2);
        }
    }
    else if (s2[0] == '-') {
        s2 = s2.substr(1);
        if (cmp(s1, s2) == true) {
            return "-" + sub(s2, s1);
        } else {
            return sub(s1, s2);
        }
    }
    else {
        return add(s1, s2);
    }
}

string Sub(string s1, string s2) {
    if (s2[0] == '-') {
        s2 = s2.substr(1);
        return Add(s1, s2);
    }
    else {
        return Add(s1, "-" + s2);
    }
}

string multi(string s1, string s2) {    // under condition: s1,s2>=0
    // 初始化部分
    int n = s1.length(), m = s2.length();
    for (int i = 0; i < n; i ++) a[i] = s1[n-1-i] - '0';
    for (int i = 0; i < m; i ++) b[i] = s2[m-1-i] - '0';
    int len = n + m;
    for (int i = n; i < len; i ++) a[i] = 0;
    for (int i = m; i < len; i ++) b[i] = 0;
    for (int i = 0; i < len; i ++) res[i] = 0;
    // 处理部分
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < m; j ++)
            res[i+j] += a[i] * b[j];
    for (int i = 0; i < len; i ++) {
        res[i+1] += res[i] / 10;
        res[i] %= 10;
    }
    // 返回部分
    int i = len-1;
    while (res[i] == 0 && i > 0) i --;
    string s = "";
    for (; i >= 0; i --) {
        char c = (char) (res[i] + '0');
        s += c;
    }
    return s;
}

pair<string, string> divide(string s1, string s2) { // under condition: s1>=0,s2>0
    string s = "", t = "";
    int n = s1.length(), m = s2.length();
    bool flag = false;
    for (int i = 0; i < n; i ++) {
        s += s1[i];
        int num = 0;
        while (cmp(s, s2) == false) {
            num ++;
            s = sub(s, s2);
        }
        if (num > 0) {
            flag = true;
            char c = (char)(num + '0');
            t += c;
        }
        else if (flag) {
            t += '0';
        }
    }
    if (t.length() == 0) t = "0";
    while (s[0] == '0' && s.length() > 1) s = s.substr(1);
    return make_pair(t, s);
}

string s = "2", t = "1", ans = "";
int P;

int main() {
    cin >> P;
    int ans_len = ceil(P * log(2) / log(10));
    cout << ans_len << endl;
    while (P > 1) {
        if (P % 2) {
            t = multi(t, s);
            if (t.length() > 500) t = t.substr(t.length()-500, 500);
        }
        s = multi(s, s);
        if (s.length() > 500) s = s.substr(s.length()-500, 500);
        P /= 2;
    }
    s = multi(s, t);
    s = Sub(s, "1");
    int len = s.length();
    if (len <= 500) for (int i = 0; i < 500 - len; i ++) ans += "0";
    if (len <= 500)
        ans += s;
    else
        ans = s.substr(len-500, 500);
    for (int i = 0; i < 10; i ++) cout << ans.substr(i*50, 50) << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/codedecision/p/11714911.html