In 2005 NOIP universal solution to a problem set rematch

The topics covered algorithm:

  • Tao Tao picking apples: entry title;
  • Tree outside the school: a simple simulation;
  • Herbs: 01 backpack;
  • Cycle: simulation, precision.

Tao Tao picking apples

Topic links: https://www.luogu.org/problem/P1046
cycle again, how to find a few less than or equal to the height of the Tata + height of the chair.
Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
int a[10], n, cnt, tt;
int main() {
    for (int i = 0; i < 10; i ++) cin >> a[i];
    cin >> tt;
    for (int i = 0; i < 10; i ++)
        if (a[i] <= tt + 30) cnt ++;
    cout << cnt << endl;
    return 0;
}

Tree outside the school

Topic links: https://www.luogu.org/problem/P1047
This question can open for the cycle of violence is not a problem, but there \ (O (n) \) algorithm that point mark, which is to open a array \ (C [] \) , for each range interval \ ([L, R & lt] \) , \ (C [L] ++ \) : indicates the \ (L \) begins some began to cut the tree, \ (C [R & lt +. 1] - \) : indicates the \ (R + 1 \) begins a period not cut the tree begins.
And then open a variable \ (tmp \) , traversing from left to right past, each \ (tmp + = CNT [I] \) , if the \ (tmp \ gt 0 \) , described \ (I \) is cut , or else \ (i \) will not be cut off.
Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;
int n, m, l, r, cnt[maxn], tmp, ans;
int main() {
    cin >> n >> m;
    while (m --) {
        cin >> l >> r;
        cnt[l] ++;
        cnt[r+1] --;
    }
    for (int i = 0; i <= n; i ++) {
        tmp += cnt[i];
        ans += !tmp;
    }
    cout << ans << endl;
    return 0;
}

Herbs

Topic links: https://www.luogu.org/problem/P1048
This question is a bare 01 knapsack problem.
Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int V, n, c, w, f[maxn];
int main() {
    cin >> V >> n;
    while (n --) {
        cin >> c >> w;
        for (int i = V; i >= c; i --)
            f[i] = max(f[i], f[i-c] + w);
    }
    cout << f[V] << endl;
    return 0;
}

cycle

Topic links: https://www.luogu.org/problem/P1050
This question is a very tedious precision analog.
Problem solution from: https://www.luogu.org/blog/user277/solution-p1050

首先,我们看数据范围10^100,就知道数据有多阴险了(一股寒意袭来)~(≧▽≦)/  
然而真正需要计算的部分就是后k位了,我们可以从尾来分析→既后1位,后2位,后3位,后4位……后k位,递推去找  
假使输入数据位198123 4  
①截取后4位8123,只需对8123做处理(输入时需注意,首先输入一个字符串,分割后存入数组)  
②首先取最后一位3,寻找循环节(此时,用布尔数组判断是否存在循环,若不存在,直接输出-1)  
3,9,7,1,*3,循环长度为4  
③此时,取后两位23:(23^4) mod 100=41 此时,23需每次乘以41,可保证最后一位不变  
 23*41^n的循环节为43 63 83 03 23 循环节长度为5,此时,循环总长度位4*5=20  
④通第3步操作,取后三位123:(123^20) mod 1000=201  
123*201^n的循环节为723 323 923 523 123 循环节长度为5,此时总长度位20*5=100
⑤还是一样,取后四位8123:(8123^100) mod 10000=6001
8123*6001^n的循环节位6123 4123 2123 0123 8123 循环节长度为5,此时总长度位100*5=500
答案就出来了
做题时需注意高精的运用和字符串处理
还需注意,每次的(n^m) mod 10^a的结果需要代到下一次中,否则会超时!(计算时,须整个后k位都要乘)

Codes are as follows:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 220;
string s, t;
bool vis[10];
int k;
string delta = "1";
int tmp_a[maxn], tmp_b[maxn], tmp_c[maxn];
string multi(string s1, string s2, int len) {
    int len1 = min( (int) s1.length(), len), len2 = min( (int) s2.length(), len);
    for (int i = 0; i < len1; i ++) tmp_a[i] = s1[len1-1-i] - '0';
    for (int i = 0; i < len2; i ++) tmp_b[i] = s2[len2-1-i] - '0';
    for (int i = 0; i < len; i ++) tmp_c[i] = 0;
    for (int i = 0; i < len1; i ++)
        for (int j = 0; j < len2; j ++)
            tmp_c[i+j] += tmp_a[i] * tmp_b[j];
    for (int i = 0; i < len; i ++) {
        tmp_c[i+1] += tmp_c[i] / 10;
        tmp_c[i] %= 10;
    }
    string res = "";
    for (int i = len-1; i >= 0; i --) {
        char c = '0' + tmp_c[i];
        res += c;
    }
    return res;
}
int tmp_d[maxn];
bool my_check(int n) {
    return n > 1 || n == 1 && tmp_d[0] > 1;
}
void my_divide2(int &n) {
    for (int i = n-1; i >= 0; i --) {
        if (tmp_d[i] % 2 && i > 0) tmp_d[i-1] += 10;
        tmp_d[i] /= 2;
    }
    while (n > 0 && tmp_d[n-1] == 0) n --;
}
string quick_mi(string s, string t, int len) {
    string tt = "1";
    memset(tmp_d, 0, sizeof(tmp_d));
    int n = t.length();
    while (n > 0 && tmp_d[n-1]) n --;
    for (int i = 0; i < n; i ++) tmp_d[i] = t[n-1-i] - '0';
    while (my_check(n)) {
        if (tmp_d[0] % 2) tt = multi(tt, s, len);
        s = multi(s, s, len);
        my_divide2(n);
    }
    return multi(s, tt, len);
}

string multi2(string s, int a) {
    int len = s.length();
    for (int i = 0; i < len; i ++) tmp_a[i] = s[len-1-i] - '0';
    memset(tmp_b, 0, sizeof(tmp_b));
    for (int i = 0; i < len; i ++) {
        tmp_b[i] += tmp_a[i] * a;
        tmp_b[i+1] += tmp_b[i] / 10;
        tmp_b[i] %= 10;
    }
    int i = maxn-1;
    while (!tmp_b[i] && i > 0) i --;
    string res = "";
    while (i >= 0) {
        char c = '0' + tmp_b[i--];
        res += c;
    }
    return res;
}
int main() {
    cin >> s >> k;
    if (s.length() < k) {
        for (int i = k-s.length(); i > 0; i --)
            s = "0" + s;
    }
    for (int len = 1; len <= k; len ++) {
        t = s.substr(s.length()-len, len);
        memset(vis, 0, sizeof(vis));
        string tmp_s = t;
        int i;
        string delta_s = quick_mi(t, delta, len);
        for (i = 1; ; i ++) {
            tmp_s = multi(tmp_s, delta_s, len);
            if (tmp_s[0] == t[0]) break;
            else if (vis[ tmp_s[0] - '0' ]) {
                cout << -1 << endl;
                return 0;
            }
            else vis[ tmp_s[0] - '0' ] = true;
        }
        delta = multi2(delta, i);

    }
    cout << delta << endl;
    return 0;
}

Author: zifeiy

Guess you like

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