第二十一届宁波大学程序设计竞赛

第二十一届宁波大学程序设计竞赛(同步赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

第二十一届宁波大学程序设计竞赛(ABDFGH)

目录

A:哈喽蘑菇

B:Love You Guys

题意:

思路:

D:爱丽丝,来扫除啦!(Easy Version)

题意:

思路:

代码:

F:奇数Alice偶数Bob!

题意:

思路:

代码思路:

G:黑天鹅的记忆解析

H:后缀0

题意:

思路:打表找规律。

代码:


A:哈喽蘑菇

签到题目:直接上代码

//https://ac.nowcoder.com/acm/contest/84302/A
#include <bits/stdc++.h>

using namespace std;

int main()
{
    cout<<"NBUCPC"<<endl;
    
    return 0;
}

B:Love You Guys

题意:

        zwh_zzz对编译原理的熟练度初始值为x,但是他每天都会遗忘这门课程的熟练度z,z是一个等差数列,首项为a,公差是b。但zwh_zzz每天教别人复习知识,又会增加熟练度y。但复习之后熟练度不会超过原始的x。问:在第几天zwh_zzz的熟练度为负数。

思路:

       输入x,y,a,b,分别代表初始熟练度,复习增加的熟练度,初始遗忘值(首项),递增的遗忘值(公差)。

        将x赋给start方便我们对复习后超过x的情况进行判断。将a赋值给jian(每日遗忘值)。循环直到熟练度小于0的时候退出。只要熟练度大于等于0,cc(天数)++,下一次遗忘值 jian+=b;

        最后输出cc即位天数。

代码:

//https://ac.nowcoder.com/acm/contest/84302/B
#include <bits/stdc++.h>

using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int x,y,a,b;
    cin>>x>>y>>a>>b;
    int start=x;
    int jian=a;
    int cc=0;
    while(x>=0){
        x=x-jian+y;
        if(x>=start){
            x=start;
        }
        jian+=b;
        cc++;
    }
    cout<<cc<<endl;
    return 0;
}

D:爱丽丝,来扫除啦!(Easy Version)

题意:

        位于原点(0,0)的Alice,有发射一条激光(射线)的能力,有坐落在无限大的xoy坐标系的垃圾点,问:Alice的这条激光,最多可以清除多少垃圾。

思路:

        1.先统计位于(0,0)点的垃圾数量chu。最大垃圾数量maxx初始为0

        2.遍历循环不是原点的垃圾,我们命名为Arubbish,已知两点确定一条直线,所以直线的斜率我们知道了,但我们不用斜率相除的模式,我们采用对角相乘来避免出现分母为0和精确度丢失的问题。

        3.但是,题目中给的是射线,且一个点在原点,所以我们还需要保证另外的点与Arubbish坐标同号。

        4.统计每次一Arubbish为射线第二点的垃圾总数cc,更新最大垃圾数量(不包括原点)maxx=max(maxx,cc)。也可以把所有的结果丢进是数组,然后最后一起从大到小排序,去数组首位。

        5.最后,将位于原点的垃圾数量chu加上最大的垃圾书maxx,输出chu+maxx。

代码:

//https://ac.nowcoder.com/acm/contest/84302/F
#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
vector<PII>point;
int n;
map<int,int>mp;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    int x;
    for(int i=0;i<n;i++){
        cin>>x;
        mp[x]++;
    }
    if(n%2==1){
        cout<<"Yukimi"<<endl;
        return 0;
    }
    map<int,int>::iterator it=mp.begin();
    int minn=it->first;
    if(minn!=1){
        int sheng=n-it->second;
        if(sheng%2==0){
            cout<<"LCF"<<endl;
        }
        else{
            cout<<"Yukimi"<<endl;
        }
    }
    else{
        int sheng=n-it->second;
        if(sheng%2==0){
            cout<<"LCF"<<endl;
        }
        else{
            cout<<"Yukimi"<<endl;
        }
    }
    return 0;
}

F:奇数Alice偶数Bob!

题意:

        有n个石堆,第i个石堆有ai个石头。Alice和LCF轮流任意挑选一个石堆里的石头取走。

规则如下:

        1.Alice先拿。

        2.不能选择石头数量为0的石堆。

        3.选择的石堆拿完石头后,选择的石堆石头数量必须小于等于所有石堆里最少的石头数量。

        4.两个人都是聪明人。

        5.当不能操作的时候就认定为输了。

思路:

考虑一下必胜态:

        1:n是奇数的时候,Alice只要拿完任意一堆石头,LCF也要这样,最后一堆一定是Alice拿的,所以,Alice赢。

        2:n是偶数的时候,最小石头数量的堆数为奇数的时候,Alice赢,反之,Bob赢。原因:Alice可以将其他不是最小石头数量minn的石堆变成minn,如果LCF将其他改成比minn还小Mminn的时候,就又变成了最初的最小石头数量的堆数为奇数,Alice继续将其他不是最小石头数量Mminn的石堆变成Mminn。如果LCF跟Alice学着做,那么最后会变成全部相同的石头堆,且轮到LCF操作。如果minn本身等于1,LCF直接直接取走1,石堆的状态变为最小值为0,剩下奇数个石堆,状态为必胜态1,轮到Alice,Alice胜利。如果minn本身不等于1,如果LCF直接取走任意一个石堆的全部石头,剩余的石头的数量为奇数,状态为必胜态1,轮到Alice,Alice胜利;如果LCF直接取走任意一个石堆,这个石堆的石头数量大于1,那么回到n是偶数,最小石头数量的堆数为奇数的初始状态。

考虑一下必输态:

        1.当前有0且剩余石头对为奇数,谁到这个状态谁必输。

代码思路:

        1.将石堆的信息分为储存在map中,方便我们统计最小石头数的石堆数量。map按照key值进行自动排序,方便。

        2.判断n是否为奇数。是奇数,输出Alice,否则继续。

        3.利用迭代器获取最小石头数量的石堆数量ans=it->second。

        3.对ans进行奇偶判断。

        4.输出结果。

//https://ac.nowcoder.com/acm/contest/84302/F
#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
vector<PII>point;
int n;
map<int,int>mp;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    int x;
    for(int i=0;i<n;i++){
        cin>>x;
        mp[x]++;
    }
    if(n%2==1){
        cout<<"Yukimi"<<endl;
        return 0;
    }
    map<int,int>::iterator it=mp.begin();
    int ans=it->second;
    if(ans%2==0){
        cout<<"LCF"<<endl;
    }
    else{
        cout<<"Yukimi"<<endl;
    }
    return 0;
}

G:黑天鹅的记忆解析

题意:

        两个字符串s,t的长度分别为n,m,n的范围在[1,3000],m的范围在[1,min(20,n)],s为记忆字符串,t为真实情报。有一个为空的字符串res,要求从s的开始处遍历,只可以将当前字符插入res的开头或是结尾,问最后的拼接成res等于t的情况有多少种情况。

思路:

        m的范围很小,只有[1,20],而且,res的最大长度为min(n,m),所以直接dfs从头插入,从尾插入,当长度==m的时候,判断res是否等于t,如果等于,答案加1。

        特别的,n<m的时候,无论怎么拼,res!=t,直接输出0。

时间复杂度:

        本题的时间复杂度受到m限制,m的最大值为20,_2{20}=1048576,在1ms的时间范围内,可以运行。

代码:

//https://ac.nowcoder.com/acm/contest/84302/G
#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
string s,t;
int n,m,cnt;
void dfs(string res,int pos){
    if(pos>=m)
    {
        if(t==res)
           cnt++;
        return;
    }
    string hou="";
    hou+=res+s[pos];
    string qian="";
    qian+=s[pos]+res;
    //cout<<pos<<"   "<<hou<<"   "<<res<<"  "<<endl;
    dfs(hou,pos+1);
    dfs(qian,pos+1);
    return;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>s>>t;
    n=s.length();
    m=t.length();
    if(n<m)
        cout<<"0"<<endl;
    else{
        int pos=0;
        string res="";
        dfs(res,pos);
        cout<<cnt<<endl;
    }

    return 0;
}

H:后缀0

题意:

        有一个整数n,求1+\sum_{i=1}^{n}(i*i!)结果的末尾有几个0。

思路:打表找规律。

        1. (1,2,3)三个数字没有0,直接输出0。

        2.末尾的0的个数为1,2,3,4,6,7,8,9,10,12,13,14,15,16,18,19,20,21,22,24……

        3.缺失的数据为5,11,17,23……构成等差数列公差为6。

        4.从4开始,每5个为一组。为1的数4,5,6,7,8。为2的数9,10,11,12,13。为3的数14,15,16,17,18。为4的数19,20,21,22,23。为6的数24,25,26,27,28......

        5.将这些数+1得到:为1的数5,6,7,8,9。为2的数10,11,12,13,14。为3的数15,16,17,18,19。为4的数20,21,22,23,24。为6的数25,26,27,28,29......

        6.将这些数n对首项为5,公比为5的等比数列进行整除的结果相加,可以得到后缀0的数量。        

代码:

//https://ac.nowcoder.com/acm/contest/84302/H
#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
ll res,n,t;
ll arr[31];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    arr[1]=5;
    for(int i=2;i<=31;i++){
          arr[i]=arr[i-1]*5;
    }
    cin>>t;
    while(t--){
        cin>>n;
        if(n==1||n==2||n==3){
            cout<<"0"<<endl;
        }
        else{
            res=0;
            n++;
            for(int i=1;i<=31;i++){
                res+=n/arr[i];
            }
            cout<<res<<endl;
        }
    }

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值