SDUT - 2017年寒假集训 阶段测试赛3(个人) -- 解题报告

来源:互联网 发布:淘宝 心语星店 编辑:程序博客网 时间:2024/06/11 04:53

比赛 ID: 2016

注:本题解参考代码均为 C++ 代码,如果你是 C 使用者,出现不认识的头文件时,若是 c 开头的,一般可以通过去掉开头的 c 然后在末尾添加 .h 来转换成 C 的头文件,如 cstdio 在 C 中为 stdio.h ,其他的请自行搜索。另外,如果出现不认识的写法,如 sort(排序)stack(栈) 等,请自行实现。


A - SDUT 2041 初级二十四点游戏

签到题,判断 m+n 和 m*n 即可。

参考代码:

#include <cstdio>using namespace std;int main(int argc, char const *argv[]) {    int m, n;    scanf("%d %d", &m, &n);    if(m+n==24 || m*n==24) printf("Yes\n");    else printf("No\n");    return 0;}

B - SDUT 3352 高数Umaru系列(3)——喵星人

用三层 for 循环枚举每种喵粮的购买数量,如果总花费小于等于 n,则记录一次方案,最后输出总方案数即可。

参考代码:

#include <cstdio>using namespace std;int main(int argc, char const *argv[]) {    int n;    while(~ scanf("%d", &n)) {        int ans = 0;        for(int i=0; i<=n/12; ++i) {            for(int j=0; j<=n/5; ++j) {                for(int k=0; k<=n/2; ++k) {                    if(i*12+j*5+k*2 <= n) ans++;                }            }        }        printf("%d\n", ans);    }    return 0;}

C - SDUT 2887 RE选老婆

用数组记录每种字母是否出现过,最后遍历一遍即可得到不同字母的个数。

参考代码:

#include <cstdio>using namespace std;int main(int argc, char const *argv[]) {    char s[101];    while(~ scanf("%s", s)) {        bool h[26] = {false}; // 标记字母是否出现过        for(int i=0; s[i]; ++i) {            h[s[i]-'a'] = true;        }        int cnt = 0;        for(int i=0; i<26; ++i) { // 计算不同字母的数量            if(h[i]) cnt++;        }        if(cnt%2 == 0) printf("GET OUT!\n");        else printf("I WANT YOU!\n");    }    return 0;}

D - SDUT 2082 Bone Collector

裸的 01 背包题,不解释。

参考代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 1000;const int MAXC = 1000;int main(int argc, char const *argv[]) {    int t, n, c, w[MAXN+1], v[MAXN+1], dp[MAXC+1];    scanf("%d", &t);    while(t--) {        scanf("%d %d", &n, &c);        for(int i=1; i<=n; ++i) {            scanf("%d", &v[i]);        }        for(int i=1; i<=n; ++i) {            scanf("%d", &w[i]);        }        memset(dp, 0, sizeof dp);        for(int i=1; i<=n; ++i) {            for(int j=c; j>=w[i]; --j) {                dp[j] = max(dp[j], dp[j-w[i]]+v[i]);            }        }        printf("%d\n", dp[c]);    }    return 0;}

E - SDUT 1021 考新郎

n 个里选 m 个的错排。应用错排公式和组合数公式即可。其中组合数公式为:n! / (m! * (n-m)!)。

参考代码:

#include <cstdio>using namespace std;const int MAX = 20;int main(int argc, char const *argv[]) {    int c, n, m;    long long a[MAX+1] = {0, 0, 1,}, f[MAX+1] = {1,};    for(int i=3; i<=MAX; ++i) {// 预处理:错排        a[i] = (i-1)*(a[i-1]+a[i-2]);    }    for(int i=1; i<=MAX; ++i) { // 预处理:阶乘        f[i] = f[i-1] * i;    }    scanf("%d", &c);    while(c--) {        scanf("%d %d", &n, &m);        printf("%lld\n", a[m]*(f[n]/(f[m]*f[n-m])));    }    return 0;}

F - SDUT 3334 数据结构实验之栈七:出栈序列判定

设置一个栈,并设置 2 个变量来存储当前入栈序列和出栈序列的遍历位置。我们可以遍历一下出栈序列,每次循环时,如果当前栈顶符合出栈序列中当前要出栈的数,则直接出栈;否则按入栈序列继续 push。如果入栈完毕而出栈序列依然没有全部符合,则不是合法的出栈序列。

参考代码:

#include <cstdio>#include <stack>using namespace std;int main(int argc, char const *argv[]) {    int n, t, a[10000], b[10000];    scanf("%d", &n);    for(int i=0; i<n; ++i) {        scanf("%d", &a[i]);    }    scanf("%d", &t);    while(t--) {        for(int i=0; i<n; ++i) {            scanf("%d", &b[i]);        }        stack<int> s;        int idx_a = 0, idx_b = 0;        while(idx_b < n) {            if(!s.empty() && s.top()==b[idx_b]) { // 栈顶符合,出栈                s.pop();                idx_b++;            }            else if(idx_a < n) s.push(a[idx_a++]); // 否则先按 a 入栈            else break; // 不满足,跳出        }        if(s.empty()) printf("yes\n"); // 如果栈已空,说明序列符合        else printf("no\n");    }    return 0;}

G - SDUT 3471 汤圆星の汤圆树

首先要使层数最少,则每层的汤圆必须尽可能连够 m 个汤圆。第 1 层为 1 个,第 2 层为 m 个,之后每一层上的汤圆都会与它的父汤圆和它的 m-1 个子汤圆连接,所以每多一层,都会多出 m-1 个子汤圆,这样,最外层的汤圆数是上一层的 m-1 倍。我们只需要不断累乘,直到最外层汤圆数不小于 n 即可。

另外需要注意特判 n=1 和 m=2 的情况(先自己思考一下为什么)。

参考代码:

#include <cstdio>using namespace std;int main(int argc, char const *argv[]) {    int m, n, ans;    while(scanf("%d %d", &m, &n), m|n) {        if(n == 1) ans = 1; // n = 1 时,只需要树根        else {            if(m == 2) { // m = 2 时,第 2 层之后每层数量不会增加                if(n == 2) ans = 2;                else ans = -1;            }            else {                ans = 2;                long long tmp = m;                while(tmp < n) { // 最外层汤圆数不足 n 时一直累乘                    tmp *= (m-1);                    ans++;                }            }        }        printf("%d\n", ans);    }    return 0;}

H - SDUT 1703 今年暑假不AC

贪心题,和「SDUT 2073 活动选择问题」几乎是一样的题,不解释。

参考代码:

#include <cstdio>#include <algorithm>using namespace std;struct info {    int s;    int e;} t[100];bool cmp(info a, info b) {    return a.e < b.e;}int main(int argc, char const *argv[]) {    int n;    while(scanf("%d", &n) && n) {        for(int i=0; i<n; ++i) {            scanf("%d %d", &t[i].s, &t[i].e);        }        sort(t, t+n, cmp);        int st = 0, ans = 0;        for(int i=0; i<n; ++i) {            if(t[i].s >= st) {                ans++;                st = t[i].e;            }        }        printf("%d\n", ans);    }    return 0;}
1 0
原创粉丝点击