2020 年 “联想杯”全国高校程序设计在线邀请赛暨第三届上海理工大学程序设计竞赛(部分题解+AC代码)

题目链接

A.Archmage

题意

大法师有n点初始魔法,每秒可以召唤一个水元素,消耗x点魔法(现有魔法不足则不能召唤),无论是否召唤,这一秒结束的时候会回复y点魔法,问m秒可以召唤多少水元素。

思路

比赛的时候想着找循环节然后开头和结尾模拟一下,但是疯狂wa。赛后补题了解到可以直接套公式。分两类情况讨论:x<=y则每秒都可以召唤水元素,即可召唤m个;x>y时,m秒的总魔法值为n+(m-1)*y(因为最后一秒回复的魔法值是在召唤后所以用不到,故m-1),召唤一个水元素消耗x点魔法,故召唤水元素为(n+(m-1)*y)/x。综合可得,ans=min(m,(n+(m-1)*y)/x).

AC代码

#include 

using namespace std;

int main()
{
    int t;
    long long x,y,n,m;
    cin >> t;
    while(t--)
    {
        cin>>n>>m>>x>>y;
        cout << min(m,(n+(m-1)*y)/x) << endl;
    }
    return 0;
}

B. Bamboo Leaf Rhapsody(签到题)

题意

给几组三维坐标,求到原点的最短距离,保留三位小数。

AC代码

#include 
#include 
using namespace std;

int main()
{
    int n,x,y,z;
    int ans=1e8;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d %d %d",&x,&y,&z);
        ans=min(ans,x*x+y*y+z*z);
    }
    printf("%.3lf",sqrt(ans*1.0));
    return 0;
}

C. Cheat Sheet

题意

给出m个单词,选取其中的部分或者全部放入n个格子里,每个单词之间空至少一格,要求放入格子中的单词不重复且数量最多。

思路

逐个输入字符 循环遍历已有单词判断是否重复,不重复则填入字符串数组,然后按照字符长度排序,优先输出短的。

AC代码

#include 
#include

using namespace std;

bool cmp(pair<string,int> p1,pair<string,int> p2)
{
        return p1.second < p2.second;
}
int main()
{

    int m,n;
    cin >> n >> m;
    string str;
    vector<pair<string,int> > vc;
    for(int i = 0; i < m ; i++)
    {
        cin >> str;
        int flag=0;
        for(int i=0;i<vc.size();i++)
        {
            if(vc[i].first==str)
                {flag=1;break;}
        }
        if(flag!=1)
        vc.push_back(make_pair(str,str.size()));
    }
    sort(vc.begin(),vc.end(),cmp);
    int ans=0;
    for(int i = 0; i <  vc.size(); i++)
    {
        n=n-vc[i].second;
        if(n>=0)
        {
            ans++;
            n--;
//            cout << vc[i].first << endl;
        }
        else break;

    }
    printf("%d\n",ans);
    return 0;
}

H. Hay Mower

题意

有一块n*m的草坪,每秒i行j列的草会生长aij那么多,有k次操作,每次操作会在t秒的时候将第x(y)行(列)的草割完,问所有操作后总割草数,数据过大取模998244353。

思路

无论什么时候割草,其实只要考虑最后一次割草的时间即可,所以可以用一个dp数组记录每个格子最后割草的时间×生长速度,遍历所有格子累加就是总割草数了,需要注意的是多个地方的取模,不然数据量过大会溢出,在代码里有体现。

AC代码

#include 
#include 
using namespace std;
long long dp[510][510];
long long mp[510][510];
int main()
{
    int n,m,k;
    cin >> n >> m >> k;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            cin >>mp[i][j];
    while(k--)
    {
        char c;
        long long x,t;
        cin >> c >> x >> t;
        if(c=='r')
        {
            for(int i=1; i<=m; i++)
            {
                if(dp[x][i]<t)
                    dp[x][i]=t;
            }
        }
        else
        {
            for(int i=1; i<=n; i++)
            {
                if(dp[i][x]<t)
                    dp[i][x]=t;
            }
        }
    }
    long long ans=0;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            ans+=(dp[i][j]%998244353)*(mp[i][j]%998244353);
            ans=ans%998244353;
        }
    }
    printf("%lld",ans);
    return 0;
}

L. Lottery Tickets

题意

给出若干个0-9的数字随意组合,求最大的能被4整除的整数。

思路

可以知道只要个位和十位数字组成的两位数能被4整除那么整个数字能被整除(因为从三位数开始整百整千整万只要是整的都能被4整除,那么加上一个能被4整除的两位数则整个数也能被整除),所以只要组出最小的两位数然后把剩余的数按照高位大数字低位小数字的原则分配即可,要注意前置0,单独一个0、4、8等情况的特判,这种做法特判太多很容易出错,我按照这种思路越改越乱,最后用了朋友的暴力求解方法,下面是他(@ZXR)的代码

AC代码

#include 

using namespace std;

const int N = 9e5 + 10;
stack<int> s;
char str[N];
int c[25], cnt;

bool get_2() {
    int a = 20, b = 20;
    for (int i = 0; i < 10; i++) {
        if (!c[i]) continue;
        c[i]--;
        for (int j = 0; j < 10; j++) {
            if (!c[j]) continue;
            if ((i * 10 + j) % 4) continue;
            if (max(i, j) < max(a, b)) {
                a = i, b = j;
            } else if (max(i, j) == max(a, b)) {
                if (min(i, j) < min(a, b)) {
                    a = i, b = j;
                } else if (min(i, j) == min(a, b) &&
                           (i * 10 + j) > (a * 10 + b)) {
                    a = i, b = j;
                }
            }
        }
        c[i]++;
    }
    if (a == 20 && b == 20) return false;
    s.push(b);
    s.push(a);
    c[a]--;
    c[b]--;
    return true;
}

void num2str() {
    cnt = 0;
    for (int i = 9; i >= 0; i--) {
        while (c[i]--) {
            str[cnt++] = i + '0';
        }
    }
    str[cnt++] = s.top() + '0';
    s.pop();
    str[cnt++] = s.top() + '0';
    s.pop();
    str[cnt] = 0;
}

int main() {
    int t, num;
    scanf("%d", &t);
    while (t--) {
        num = 0;
        bool f = false;
        memset(c, 0, sizeof(c));
        for (int i = 0; i < 10; i++) {
            scanf("%d", &c[i]);
            num += c[i];
            if (c[i] && i) f = true;
        }
        if (!f) {
            printf("0\n");
        } else if (num == 1) {
            for (int i = 0; i < 10; i++) {
                if (c[i] == 1) {
                    if (i % 4)
                        printf("-1\n");
                    else {
                        printf("%d\n", i);
                    }
                    break;
                }
            }
        } else {
            if (!get_2()) {
                bool flag = false;
                for (int i = 8; i >= 0; i -= 4) {
                    if (c[i]) {
                        printf("%d\n", i);
                        flag = true;
                        break;
                    }
                }
                if (!flag) printf("-1\n");
            } else {
                num2str();
                printf("%s\n", str);
            }
        }
    }
    return 0;
}

总结

这次比赛被大法师卡了好久好久,最后也没A出来,时间不够只A出了两道,好菜好菜,思维还是得多锻炼,对题目不够敏感,还是得多刷题,为了自己的初心,不负努力,继续加油吧。

你可能感兴趣的:(ACM秃头历程)