7.16

集训的第一天,不知道能不能走到最后


Uva120煎饼
题意:有一串串的序列,要求每次选定一个点,将这个点以上的序列进行翻转,最终态是要求整个序列为升序
解法:每次考虑最高的元素,先将其反转到最高位,再反转到对应的位置
代码如下:

#include<cstdio>
#include<string>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> a, st,mid;
queue<int>q;
//FILE*fp = fopen("stdout.txt", "w");

int main() {
    st.resize(1);
    while (scanf("%d", &st[0])!=EOF && st[0]) {
        int tmp = st[0], num = 1;
        st.clear(); st.push_back(tmp);
        while (getchar() != '
') {
            ++num; scanf("%d", &tmp);
            st.push_back(tmp);
        }
        a.assign(st.begin(), st.end());
        mid.assign(st.begin(), st.end());
        sort(st.begin(), st.end());
        for (int i = num - 1; i >= 0; i--) {
            int numm = st[i], pos = find(a.begin(), a.end(), numm) - a.begin();
            if (pos != i) {
                if (pos != 0) {
                    reverse(a.begin(), a.begin() + pos + 1);
                    q.push(num - pos);
                }
                reverse(a.begin(), a.begin() + i + 1);
                q.push(num - i);
            }
        }
        q.push(0);
        //cout << s << endl;
        printf( "%d", mid[0]);
        for (int i = 1; i < num; i++)printf( " %d", mid[i]);
        printf( "
%d", q.front()); q.pop();
        while (!q.empty()) {
            printf( " %d", q.front()); q.pop();
        }printf( "
");
    }
    return 0;
}

集训队题集链接
A题:
简单的求平均数,没什么的,注意题目说了最长和不超过5000

#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 1e4 + 5;
int n, a[maxn];

int main() {
    while (scanf("%d", &n) && n != 0) {
        int sum = 0, num = 0;
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            sum += a[i];
        }
        sum /= n;
        for (int i = 0; i < n; i++) {
            if (a[i] <= sum)num++;
        }
        printf("%d
", num);
    }
    return 0;
}

L题:
题意:有一列数,要求得两个数,要求这两个数的和是小于题目给定数里面最大的,输出这两个数的和
思路:二分蜜汁算不出来,只能手写

#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
const int maxn = 1e3 + 5;
int a[maxn];
int n, m;
set<int>s;

int main() {
    while (scanf("%d %d", &n, &m)) {
        s.clear();
        if (n == 0 && m == 0)break;
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
        }
        int max = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(i!=j) s.insert(a[i] + a[j]);
            }
        }
        //set<int>::iterator it = s.upper_bound(m);
        bool flag = false;
        for (set<int>::iterator it = --s.end(); it != s.begin(); it--) {
            if (*it <= m) {
                printf("%d
", *it);
                flag = true;
                break;
            }
        }
        if (!flag) {
            if (*s.begin() <= m) printf("%d
", *s.begin());
            else printf("NONE
");
        }
    }
    return 0;
}

C题:
这道题可以说是挺难的;
题意:给定一列数,要求得1~b中最长的连续序列,且这段数列的和恰好为b
解法:首先先求出这段数列的最长可能长度为:sqrt((ll)(b * 2)),然后根据等差数列求和公式计算首项以及区间和,最后输出结果

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
ll b;

int main() {
    while (scanf("%lld",&b) && b != 0) {
        ll len= sqrt((ll)(b * 2));
        ll tmp;
        bool flag = false;
        while (len&&!flag) {
            tmp = b / len - (len - 1) / 2;//tmp为起始数字
            if (tmp*len + len*(len - 1) / 2 == b) {//等差数列根据长度求和公式
                flag = true;
                printf("%lld %lld
", tmp, len);
            }
            len--;
        }
    }
    return 0;
}

B题:
题意:不停的折叠一张纸,要求最后输出给定点的位置的纸的层数
解法:模拟即可,这道题我觉得比较难的地方在于平移时确定起始点的位置确定,因为他能不断向上向右折,所以要把初始点的位置放到左下角,这样不断的折就可以实现不越界,同时要注意更新维护两条边的长度,总之是到不错的题

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n, m, t, p, mo=940;
int a[1005][1005];

int main() {
    while(scanf("%d%d%d%d", &n, &m, &t, &p)!=EOF) {//n是长,m是宽
        if (!n && !m && !t && !p)break;
        int d, c, lenn = 0, lenm = 1000;
        for (int i = 0; i <= 1000; i++) {
            for (int j = 0; j <= 1000; j++) {
                a[i][j] = 0;
            }
        }
        for (int i = lenm-m+1; i <=lenm; i++)
            for (int j = 0; j <n; j++) {
                a[i][j] = 1;
            }
        mo = lenm - m + 1;
        for (int k = 0; k < t; k++) {
            scanf("%d%d", &d, &c);
            if (d == 1) {//横向折叠
                for (int x = 0; x < c; x++) {
                    for (int i = mo; i < lenm +1; i++) {
                        a[i][lenn + c + x] += a[i][lenn + c - x - 1];
                    }
                }
                if (c * 2 > n) n = c * 2 - n + n - c;
                else n = n - c;
                lenn += c;
            }
            else if (d == 2) {//纵向折叠
                for (int x = 0; x < c; x++) {
                    for (int j = lenn; j < lenn + n; j++) {
                        a[lenm - c - x][j] += a[lenm - c + x + 1][j];
                    }
                }
                if (c * 2 > m) { m = c * 2 - m + m - c; mo -= m; }
                else { m = m - c; }
                lenm -= c;
            }
        }
        for (int k = 0; k < p; k++) {
            scanf("%d%d", &d, &c);
            printf("%d
", a[lenm - c][d + lenn]);
        }
    }
    return 0;
}

K题
题意:这道题的目的是给定一个字符串,要求对字符串进行一定的解析,如果两个字符串相同就输出IDENTICAL,如果只有一个引号内的内容不一样,就是CLOSE,其他情况就是DIFFERENT
思路:注意这道题模拟的时候不能把所有的引号内的内容提出来在来判断剩余的东西一样不一样,这种思路无法过最后一个样例。我们选择栈的思路进行求解。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
using namespace std;
string s1, s2;
string s, ss;
stack<char>st1, st2;

int legal() {
    int flag=0;
    while (st1.size() != 0 && st2.size() != 0) {
        char mid1 = st1.top(); st1.pop();
        char mid2 = st2.top(); st2.pop();
        if (mid1 != mid2)  return 0; 
        s.clear(); ss.clear();
        if (mid1 == '"') {
            while (st1.top() != '"') {
                s.push_back(st1.top()); st1.pop();
            }st1.pop();
            while (st2.top() != '"') {
                ss.push_back(st2.top()); st2.pop();
            }st2.pop();
            if (s != ss)
                if (flag == 0) { flag++; continue; }
                else return 0;
        }
    }
    if (st1.size() == 0 && st2.size() == 0)
        if (flag == 1)return 1;
        else return 2;
    else return 0;
}

int main() {
    while (cin >> s1&&s1[0] != '.') {
        cin >> s2;
        while (!st1.empty())st1.pop();
        while (!st2.empty())st2.pop();
        for (int i = 0; i < s1.size(); i++) st1.push(s1[i]);
        for (int i = 0; i < s2.size(); i++) st2.push(s2[i]);
        switch (legal()) {
        case 0: printf("DIFFERENT
"); break;
        case 1: printf("CLOSE
"); break;
        case 2: printf("IDENTICAL
"); break;
        }
    }
    return 0;
}

今天的表现一般,明天要继续加油

原文地址:https://www.cnblogs.com/romaLzhih/p/9489810.html