第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛

第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛

寒假打的一场比赛,时隔许久对这场比赛还有些许印象,所以特意回来补了这场比赛的题目。

小宝的幸运数组(B题)
题目链接

#include <iostream>
#include <cstring>
using namespace std;
#define N 100005
int number[N],sum[N],pos[N];
int main()
{
    int _;
    cin >> _;
    while(_--)
    {
        memset(sum,0,sizeof(sum));
        memset(pos,-1,sizeof(pos));
        int n,k;
        cin >> n >> k;
        for(int i=1;i<=n;i++)
            cin >> number[i];
        pos[0]=0;
        int ans=-1;
        for(int i=1;i<=n;i++)
        {
            sum[i]=(sum[i-1]+number[i])%k;
            if(pos[sum[i]]==-1)
                pos[sum[i]]=i;
            else
                ans=max(ans,i-pos[sum[i]]);
        }
        cout << ans << endl;
    }
    return 0;
}

前缀和求余直接模拟即可。

上进的凡凡(C题)
题目链接

#include <iostream>
using namespace std;
#define N 100005
int number[N];
int main()
{
    int n;
    cin >> n;
    for(int i=1;i<=n;i++)
        cin >> number[i];
    number[n+1]=-1;
    long long ans=0,cnt=1;
    for(int i=2;i<=n+1;i++)
    {
        if(number[i]>=number[i-1])
            cnt++;
        else
        {
            ans+=cnt*(cnt+1)/2;
            cnt=1;
        }
    }
    cout << ans << endl;
    return 0;
}

直接模拟即可。

Seek the Joker I(D题)
题目链接
一看出题人就是老柚子厨了,题目背景来自柚子社创立十周年纪念作《千恋万花》,是一款和风gal。没玩过《千恋万花》也没关系,题目的大意就是芳乃酱和丛雨酱在博弈,芳乃酱yyds!!!
声明:本题中的所有角色在剧情发生时均已超过18岁。(众所周知柚子社作品老十八禁了)

#include <iostream>
using namespace std;
int main()
{
    int _;
    cin >> _;
    while(_--)
    {
        int n,k;
        cin >> n >> k;
        if((n-1)%(k+1))
            cout << "yo xi no forever!" << endl;
        else
            cout << "ma la se mi no.1!" << endl;
    }
    return 0;
}

回到题目本身,这是一道典型的巴什博弈题目。巴什博弈的根本是破坏对方的目的以达到自己的目的。由于芳乃酱先手且拿到最后一张牌的人输,那么芳乃酱的任务就是在自己的回合内将剩下的n-1张牌拿光,这样才能获胜。我们称丛雨酱和芳乃酱各拿一次牌为一个回合,那么可以保证一回合内只要芳乃酱愿意且牌足够的情况下,这一个回合就一定能够拿完k+1张牌,所以只要剩下的n-1张牌对k+1求余还有余数的情况下,芳乃酱就一定能够获胜,只要芳乃酱第一次拿(n-1)%(k+1)张牌,经过(n-1)/(k+1)轮之后,就只剩下一张牌且轮到丛雨酱去抽,所以芳乃酱就一定会获胜。反之,如果(n-1)%(k+1)为0的话,芳乃酱就一定会输,因为不能拿0张牌。

成绩查询ing(F题)
题目链接

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
struct Stu
{
    int grade;
    int id;
    int gender;
};
map <string,Stu> mp1;
map <int,vector <string> > mp2;
string ans[105];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int n;
    cin >> n;
    while(n--)
    {
        string name;
        int grade,gender,id;
        cin >> name >> grade >> gender >> id;
        mp1[name]={grade,id,gender};
        mp2[grade].push_back(name); 
    }
    for(auto i:mp2)
    {
        auto f=i.first;
        auto s=i.second;
        sort(s.begin(),s.end());
        for(int i=0;i<s.size();i++)
            ans[f]+=s[i]+'\n';
    }
    int m;
    cin >> m;
    while(m--)
    {
        int opt;
        cin >> opt;
        if(opt==1)
        {
            string name;
            cin >> name;
            cout << mp1[name].grade << " " << mp1[name].id << " " << mp1[name].gender << endl;
        }
        if(opt==2)
        {
            int grade;
            cin >> grade;
            cout << ans[grade];
        }
    }
    return 0;
}

典型的考察数据结构的题目,题目的难点是处理这两个查询,查询一可以用一个<string,sturct>类型的map来解决,查询二可以用一个<int,vector>类型的map来解决,注意看这里处理第二个map的代码,将第二个map里的元素提前按字典序sort好存在string型的数组里,方便查询,这样一来,查询一所用的时间是O(logn),查询二所用的时间是O(1)。

买花(I题)
题目连接

#include <iostream>
#include <cmath>
using namespace std;
int sum[20];
int main()
{
    for(int i=1;i<=15;i++)
        sum[i]=pow(2,i)-1;
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        cin >> n;
        int flag=0;
        for(int i=2;i<=15;i++)
        {
            if(n%sum[i]==0)
            {
                flag=1;
                break;
            }
        }
        if(flag)
            cout << "YE5" << endl;
        else
            cout << "N0" << endl;
    }
    return 0;
}

将2的幂次方减1提前打好表,每输入一个数,就跑循环判断它是否是这些表中的数的倍数,如果是则输出“YE5”,都不是则输出“N0”。

这是一题简单的模拟
题目链接

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 305
#define INF 0x7fffffff
int mp[N][N],number[2*N],vis[N];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int u,v,cost;
        scanf("%d%d%d",&u,&v,&cost);
        mp[u][v]=cost;
        mp[v][u]=cost;
    }
    int k;
    scanf("%d",&k);
    int flag=0,ans=INF;
    while(k--)
    {
        memset(vis,0,sizeof(vis));
        int num;
        scanf("%d",&num);
        for(int i=1;i<=num;i++)
            scanf("%d",&number[i]);
        number[0]=number[n+1]=0;
        if(num!=n)
            continue;
        else
        {
            int i,sum=0;
            for(i=0;i<=num;i++)
            {
                if(vis[number[i]]||!mp[number[i]][number[i+1]])
                    break;
                vis[number[i]]=1;
                sum+=mp[number[i]][number[i+1]];
            }
            if(i>num)
                flag=1,ans=min(ans,sum);
        }
    }
    if(!flag)
        printf("-1\n");
    else
        printf("%d\n",ans);
    return 0;
}

题目确实是一道模拟题,按照题目给出的要求一个一个去模拟即可,数据量较小(300),直接开二维数组跑。

黑洞密码(K题)
题目链接

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
    string s;
    cin >> s;
    string s1,s2;
    for(int i=0;i<32;i++)
    {
        if(s[i]>='A'&&s[i]<='Z'||s[i]>='a'&&s[i]<='z')
            s1+=s[i];
        else
            s2+=s[i];
    }
    for(int i=0;i<16;i++)
    {
        if(s1[i]>='A'&&s1[i]<='Z')
        {
            s1[i]+=s2[i]-'0';
            if(s1[i]>=91)
                s1[i]+=7;
        }
        else
        {
            s1[i]-=32;
            s1[i]+=s2[i]-'0';
            if(s1[i]>=91)
                s1[i]-=57;
            s1[i]+=32;
        }
    }
    reverse(s1.begin(),s1.begin()+4);
    reverse(s1.begin()+4,s1.begin()+8);
    reverse(s1.begin()+8,s1.begin()+12);
    reverse(s1.begin()+12,s1.begin()+16);
    cout << s1 << endl;
    return 0;
}

模拟题可真不少,这道题也是按要求模拟即可,要求还不少,要求‘z’之后是‘B’,‘Z’之后是‘b’,有些小麻烦。要注意到如果给‘z’加上一个个位数是有可能超出char的上限的,所以如果是小写字母的话可以先减去一个32让其变成大写字母来处理,最后再加上32变回去。

建立火车站(L题)
题目链接

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 100005
long long number[N],dis[N];
int main()
{
    int n,k;
    cin >> n >> k;
    for(int i=1;i<=n;i++)
        cin >> number[i];
    sort(number+1,number+1+n);
    for(int i=1;i<n;i++)
        dis[i]=number[i+1]-number[i];
    long long Max=0;
    for(int i=1;i<n;i++)
        if(dis[i]>Max)
            Max=dis[i];
    long long l=1,r=Max;
    while(l<r)
    {
        long long m=(l+r)/2;
        long long sum=0;
        for(int i=1;i<n;i++)
            sum+=ceil((double)dis[i]/m)-1;
        if(sum<=k)
            r=m;
        else
            l=m+1;
    }
    cout << l << endl;
    return 0;
}

很容易想到这道题是二分答案,需要注意用floor和ceil函数的时候一定要先转换成double型再调用函数,要不然一直WA,之前就在这里犯过错这次又犯了……二分答案还是没啥好说的,直接做就可以了,关键就是这个边界的问题,每道题跟每道题都略有不同,自己还判断不出来,只能一点一点撞,啊这。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值