再戦を設定し、問題に2003年にはNOIPユニバーサルソリューション

トピックカバーアルゴリズム:

  • 卓球:単純な文字列のシミュレーション。
  • 数字のゲーム:DP間隔。
  • スタック:カトレアの数
  • マイセン番号:精度、高速パワー、数学。

卓球

トピックリンク:https://www.luogu.org/problem/P1042
この質問はイライラが、難しいことではない、より複雑な文字列のシミュレーションです。
「E」は、すべての文字列に格納され、その後、条件が満たされた場合、当選lose_pointスコアによって相手を格納するために、win_point勝利とのスコアを格納するために、列を横切るまで、私は、コード入力すると考えられ(win_point>=11 || lose_point>=11) && abs(win_point-lose-point)>=2、その後、イニングは、(21点満点の共感)終了します。
ここで注意すべきことの一つは、次のとおりです(「:0 0」が、また出力)私は最終的に出力電流の文現在のスコアにする必要があります。
次のようにコードは次のとおりです。

#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;
}

数字ゲーム

トピックリンク:https://www.luogu.org/problem/P1043
間隔DP:この質問は、知識を必要とします。
それはリングを必要とするが、我々は、このリングを開くことができます。
私たちは、入力がされていると仮定(A_1、\ DOTS、A_N \)を\その後、我々はできます、

  • 注文\(合計は、[I] \)を表す\(A_1 + \ドット+ a_iを \を)
  • オーダー\(MAXV [I] [J ] [K] \) の間隔を表す\([I、J]を\ ) に及ぶ\(K \)得られる最大の製品の部品。
  • オーダー\(MAXV [I] [J ] [K] \) の間隔を表す\([I、J]を\ ) に及ぶ\(K \)最大製品部品を得ることができます

次のように状態遷移方程式が得られる:
\(MAXV [I] [J] [K] = MAX(MAXV [I] [J] [K]、MAXV [I] [L] [K-1] * get_mod(SUM [ J] -sum [L]))\)
\(MINV [I] [J] [K] =分(MINV [I] [J] [K]、MINV [I] [L] [1-K] * get_mod(和[J] -sum [ L]))\)

ここで、\(get_mod(A)\)得るための\(\ MOD 10 \)の結果を。

その後:
最大値は(MAXV [1]〜[N \ ] [M] \) を満たす全ての条件\(MAXV [I] [J ] [M-1] * get_mod(SUM [I-1] +和[ N] - [J])\ )合計最大値、
最小値である\(MINV [1] [N ] [M] \) を満たす全ての条件\(MINV [I] [J ] [M-1 ] * get_mod(和[I- 1]和N] + [ -和[J])\) の最小値。
これは確かに、ほとんど唯一のいくつかのために、最も外側のリングをリングの問題を解決するだろう。
次のようにコードは次のとおりです。

#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;
}

スタック

トピック説明:https://www.luogu.org/problem/P1044
この質問は、以下の式を使用して、私は(もちろんそこに再発式)を行う直接設定式「のカトレア番号」、である:
\(Ciは= \ですfrac1 {N + 1} C_ {
2N} ^ \)nは次のようにコードがあります:

#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;
}

麦森数

トピックリンク:https://www.luogu.org/problem/P1045
この質問は一目+クイック高精度の力です。
最適化、すなわち、長さ、Pは、バイナリビットの数であり、そしてそれは、すべての小数で連続的でないであろうがある\(9 \) そう\(2 ^ P-1 \ ) 認識と\が( 2 ^ P \)は、同じビット数を有します。
そう式によって直接の長さ\(\ lceil P \時間\ FRAC {\ 2ログ} \ rceil \ {\ 10をログは}) が得られます。
そして、最も暴力的な急速な精度電力は、時間外の力はあるが、私たちは、プロセスは(500の終わりに傍受)これ以上500以下を相殺することを保証するために、操作を考慮にあれば、それはタイムアウトしません。
(そして、私は年上だったと私は恥ずかしいテンプレートを書いた前ので、精度の操作が直接移動-私たちはまだ、main関数のように見える、multi機能は高精度の乗算であるSub機能精密カットで)
次のようにコードは次のとおりです。

#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;
}

おすすめ

転載: www.cnblogs.com/codedecision/p/11714911.html