2018年新生中软ACM程序设计大赛决赛 -题解

今天是院ACM新生赛的决赛啦, 题目出的比较难, 最多为9道
在这里插入图片描述
可以看到大部分还是WA一片

下面是题解, 有两道题太过简单 只提供了思路.

A 外币兑换

//签到题, 从下面几个中选一个最大的, 相乘保留两位小数就行了

B polygon

//其实就是求多边形的内角和公式, 即使忘了应该想一下也就能推出来180*(n-2)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
usingnamespacestd;
#definems(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=1e6+10;

int main()
{
	LL n;
	while(scanf("%lld",&n)!=EOF){
	printf("%lld\n",(n-2)*180);
	}
	return 0;
}

C 赌气球

//完全根据来题意模拟就好了, 两个细节注意一下, 有有可能玩不够k次游戏就结束啦, 游戏结束前也要先输出Not enough token.

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 1e6+10;

int T, k, n1, b, t, n2;
int solve()
{
    if(t > T)
        return -1;
    else if(n1 < n2){
        if(b == 1){
            T+=t;
            return 1;
        }
        else if(b == 0){
            T-=t;
            T = max(0, T);
            return 0;
        }
    }
    else if(n1 > n2){
        if(b == 0){
            T+=t;
            return 1;
        }
        else if(b == 1){
            T-=t;
            return 0;
        }
    }
}
int main()
{
    cin >> T >> k;

    while(k--){
        cin >> n1 >> b >> t >> n2;
        int flag = solve();

        if(flag == -1)
            printf("Not enough tokens.  Total = %d.\n",T);
        else if(flag == 1)
            printf("Win %d!  Total = %d.\n",t,T);
        else if(flag == 0)
            printf("Lose %d.  Total = %d.\n",t,T);

        if(T <= 0){
            printf("Game Over.\n");
            break;
        }
    }

    return 0;
}

D 胡辣汤店

//斐波那契数列, 记得用long long

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define ms(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=85;

int from,to;
LL cusNum[maxn];
void init()
{
    ms(cusNum,0);
    cusNum[1]=1,cusNum[2]=1;
    for(int i=3;i<=maxn;i++)
        cusNum[i]=cusNum[i-1]+cusNum[i-2];
}
int main()
{
    init();
    while(cin>>from>>to){
        LL sum=0;
        for(int i=from;i<=to;i++)
            sum+=cusNum[i];
        cout<<sum<<endl;
    }
    return 0;
}

E 害死人不偿命的猜想

//数据量不大, 直接用递归算法处理一下即可, 终止条件是n==1, 判读奇偶对应处理即可

F 奖学金

//这道题是一道贪心算法的最基础的题目, 贪心算法很好理解, 就算每次都处理最优解, 最终结果就一定是最优解, 这道题目就算每次都取最大能取的面额, 直到为0

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define ms(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=85;


int money[]={1,5,10,20,50,100};
int main()
{
    int n,cont=0;
    cin>>n;

    while(n>0){
        for(int i=5;i>=0;i--)
            if(n>=money[i]){
                cont+=(n/money[i]);
                n%=money[i];
            }
    }
    cout<<cont<<endl;
}

G筛法

//这道题用到了筛法求素数(getPrime()函数), 而且要把素数提前预处完毕, 不能说用到一次再处理一次, 先测试一下可知n为104时最大取104729内的素数, 然后就求出104729以内的所有素数就好了, 之后遍历循环输出即可

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 104729;

bool isPrime[maxn];
int primeNum[maxn];
void getPrime()
{
    ms(primeNum, 0);
    for(int i = 2; i <= maxn; i++)
        if(!isPrime[i])
            for(int j = 2; i*j <= maxn; j++)
                isPrime[i*j] = 1;
    int tag = 1;
    for(int i = 2; i <= maxn; i++)
        if(!isPrime[i])
            primeNum[tag++] = i;
}
int main()
{
    getPrime();
    int m, n;
    cin >> m >> n;
    int tag = 0; //是否是第一个数
    for(int i = primeNum[m]; i <= primeNum[n]; i++){
        if(!isPrime[i]){
            if(tag==0) printf("%d",i), tag++;
            else printf(" %d",i), tag++;
            if(tag==10)
                printf("\n"), tag = 0;
        }
    }
	return 0;
}

H maze

//这道题是一道简单搜索的题目, 搜索其实就算递归处理, 迷宫求解: 题意是n阶方阵中判断能否从左上角走到右下角, 走法是上下左右.

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 35;
int maze[maxn][maxn], vis[maxn][maxn]; //vis表示是否走过
int T, n;
int action[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
int flag;
void Dfs(int x, int y)
{ //迷宫走到x,y时
    if(x==n && y == n){
        flag = 1;
        return; //1表示可走
    }

    for(int i = 0; i < 4; i++){
        int tx = x+action[i][0], ty = y+action[i][1];
        if(!vis[tx][ty] && maze[tx][ty] && tx>=1 && tx<=n && ty>=1 && ty<=n){
            vis[tx][ty] = 1;
            Dfs(tx, ty);
            vis[tx][ty] = 0; //回溯法处理
        }
    }
    return; //0表示不可走
}
int main()
{
    scanf("%d",&T);
    while(T--){
        memset(maze, 0, sizeof(maze)); //初始化
        memset(vis, 0, sizeof(vis));
        flag = 0;

        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%d",&maze[i][j]);

        vis[1][1] = 1;
        Dfs(1, 1); //初始状态

        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

I 开心报道

//最简单的动态规划问题 - 01背包问题, 定义dp[i][j]作为一个状态, 然后根据题意寻得状态转移方程dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 1e5+10;

int W, n, w[maxn], v[maxn];
int dp[110][maxn]; //在前i个物品中选容量不超过j时的最大价值
int main()
{
    cin >> n >> W;
    for(int i = 1; i <= n; i++)
        cin >> w[i] >> v[i];

    //动态规划
    ms(dp, 0);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= W; j++){
            if(j >= w[i])
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);
            else
                dp[i][j] = dp[i-1][j];
        }


    cout << dp[n][W] << endl;

    return 0;
}

J 阶乘的和

//高精度模板即可

#include <algorithm> // max
#include <cassert>   // assert
#include <cstdio>    // printf,sprintf
#include <cstring>   // strlen
#include <iostream>  // cin,cout
#include <string>    // string类
#include <vector>    // vector类

using namespace std;

struct BigInteger {
    typedef unsigned long long LL;

    static const int BASE = 100000000;
    static const int WIDTH = 8;
    vector<int> s;

    BigInteger &clean() {
        while (!s.back() && s.size() > 1)s.pop_back();
        return *this;
    }

    BigInteger(LL num = 0) { *this = num; }

    BigInteger(string s) { *this = s; }

    BigInteger &operator=(long long num) {
        s.clear();
        do {
            s.push_back(num % BASE);
            num /= BASE;
        } while (num > 0);
        return *this;
    }

    BigInteger &operator=(const string &str) {
        s.clear();
        int x, len = (str.length() - 1) / WIDTH + 1;
        for (int i = 0; i < len; i++) {
            int end = str.length() - i * WIDTH;
            int start = max(0, end - WIDTH);
            sscanf(str.substr(start, end - start).c_str(), "%d", &x);
            s.push_back(x);
        }
        return (*this).clean();
    }

    BigInteger operator+(const BigInteger &b) const {
        BigInteger c;
        c.s.clear();
        for (int i = 0, g = 0;; i++) {
            if (g == 0 && i >= s.size() && i >= b.s.size()) break;
            int x = g;
            if (i < s.size()) x += s[i];
            if (i < b.s.size()) x += b.s[i];
            c.s.push_back(x % BASE);
            g = x / BASE;
        }
        return c;
    }

    BigInteger operator-(const BigInteger &b) const {
        assert(b <= *this); // 减数不能大于被减数
        BigInteger c;
        c.s.clear();
        for (int i = 0, g = 0;; i++) {
            if (g == 0 && i >= s.size() && i >= b.s.size()) break;
            int x = s[i] + g;
            if (i < b.s.size()) x -= b.s[i];
            if (x < 0) {
                g = -1;
                x += BASE;
            }
            else g = 0;
            c.s.push_back(x);
        }
        return c.clean();
    }

    BigInteger operator*(const BigInteger &b) const {
        int i, j;
        LL g;
        vector<LL> v(s.size() + b.s.size(), 0);
        BigInteger c;
        c.s.clear();
        for (i = 0; i < s.size(); i++) for (j = 0; j < b.s.size(); j++) v[i + j] += LL(s[i]) * b.s[j];
        for (i = 0, g = 0;; i++) {
            if (g == 0 && i >= v.size()) break;
            LL x = v[i] + g;
            c.s.push_back(x % BASE);
            g = x / BASE;
        }
        return c.clean();
    }

    BigInteger operator/(const BigInteger &b) const {
        assert(b > 0);  // 除数必须大于0
        BigInteger c = *this;       // 商:主要是让c.s和(*this).s的vector一样大
        BigInteger m;               // 余数:初始化为0
        for (int i = s.size() - 1; i >= 0; i--) {
            m = m * BASE + s[i];
            c.s[i] = bsearch(b, m);
            m -= b * c.s[i];
        }
        return c.clean();
    }

    BigInteger operator%(const BigInteger &b) const { //方法与除法相同
        BigInteger c = *this;
        BigInteger m;
        for (int i = s.size() - 1; i >= 0; i--) {
            m = m * BASE + s[i];
            c.s[i] = bsearch(b, m);
            m -= b * c.s[i];
        }
        return m;
    }

    // 二分法找出满足bx<=m的最大的x
    int bsearch(const BigInteger &b, const BigInteger &m) const {
        int L = 0, R = BASE - 1, x;
        while (1) {
            x = (L + R) >> 1;
            if (b * x <= m) { if (b * (x + 1) > m) return x; else L = x; }
            else R = x;
        }
    }

    BigInteger &operator+=(const BigInteger &b) {
        *this = *this + b;
        return *this;
    }

    BigInteger &operator-=(const BigInteger &b) {
        *this = *this - b;
        return *this;
    }

    BigInteger &operator*=(const BigInteger &b) {
        *this = *this * b;
        return *this;
    }

    BigInteger &operator/=(const BigInteger &b) {
        *this = *this / b;
        return *this;
    }

    BigInteger &operator%=(const BigInteger &b) {
        *this = *this % b;
        return *this;
    }

    bool operator<(const BigInteger &b) const {
        if (s.size() != b.s.size()) return s.size() < b.s.size();
        for (int i = s.size() - 1; i >= 0; i--)
            if (s[i] != b.s[i]) return s[i] < b.s[i];
        return false;
    }

    bool operator>(const BigInteger &b) const { return b < *this; }

    bool operator<=(const BigInteger &b) const { return !(b < *this); }

    bool operator>=(const BigInteger &b) const { return !(*this < b); }

    bool operator!=(const BigInteger &b) const { return b < *this || *this < b; }

    bool operator==(const BigInteger &b) const { return !(b < *this) && !(b > *this); }
};

ostream &operator<<(ostream &out, const BigInteger &x) {
    out << x.s.back();
    for (int i = x.s.size() - 2; i >= 0; i--) {
        char buf[20];
        sprintf(buf, "%08d", x.s[i]);
        for (int j = 0; j < strlen(buf); j++) out << buf[j];
    }
    return out;
}

istream &operator>>(istream &in, BigInteger &x) {
    string s;
    if (!(in >> s)) return in;
    x = s;
    return in;
}

BigInteger solve(int n)
{
    BigInteger ret = 1;
    for(int i = n; i > 1; i--)
        ret *= i;
    return ret;
}
int main()
{
    int n;
    cin >> n;
    BigInteger s = 1;
    for(int i = 2; i <= n; i++)
        s += solve(i);
    cout << s << endl;
}

猜你喜欢

转载自blog.csdn.net/a1097304791/article/details/84898302
今日推荐