湖南科技大学2021年大学生计算机程序设计新生赛

问题 A: 新的希望
时间限制: 1 Sec  内存限制: 128 MB

题意:

        输入仅一个大于2021的整数。输出“A New Hope”;

解析:

        直接输出“A New Hope”即可。

主要代码:

void solve()
{
    int n;
    cin >>n;
    cout <<"A New Hope";
}

问题 B: 嘉嘉的队伍配置

时间限制: 1 Sec  内存限制: 128 MB

题意:

        现有了n位输出角色和m位辅助角色,而且每位角色最多只能加入一个队伍。现在他想配置尽可能多的“强力的队伍”,求最多能配置多少支“强力的队伍”?

一支“强力的队伍”,必须要同时满足以下三个条件:
1、队伍中的角色人数为4,即达到队伍的最大人数
2、队伍中至少要拥有一位输出角色
3、队伍中至少要拥有一位辅助角色

解析:

        贪心思维,首先将一位输出和一位辅助放在一队,看能组成多少队,显然取决取两者间位数小的那个角色,然后就是补全,看看分完之后多出来几位角色,将他们补至前面空缺能凑成多少强力的队伍,然后在剩下的队伍之间互相补全(也可能前面已经补完空缺),两者凑出来的“强力的队伍”之和即为结果。

主要代码:

void solve()
{
    int n,m,ans=0;
    cin >>n>>m;
    int k=max(n,m)-min(n,m);
    int res=min(n,m);
    if(k/2>=res)
    {
        cout <<res<<endl;
    }else{
        cout <<k/2+(res-k/2)/2<<endl; 
    }
}

问题 C: 寻找厄咒图腾

时间限制: 1 Sec  内存限制: 128 MB

题意:

        使用"hex"表示图腾,可以随意删除字符串中的字母,然后,每当在删除后的字符串中完整地组合出一个"hex"这个词,我们就认为找到一个图腾。例如:长度为5的字符串"heexh",删除两个字符后变成"hex",有一个图腾。长度为9的字符串"ehehexhex",删去前三个字符后变成"hexhex",有两个图腾。求最后可以从照片中找到的最多的图腾的数量。

解析:

        hex是有顺序的,exh不是一个图腾,那么我们可以从找到一个h开始计数,找到h再找e,找到e再找x,直到找到x后重新开始找h。

主要代码:

void solve()
{
    int n,ans=0,h=0,e=0;
    string s;
    cin >>n>>s;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='h') h++;
        if(h!=0&&s[i]=='e') e++;
        if(h!=0&&e!=0&&s[i]=='x')
        {
           e=0;h=0;ans++;   
        }
    }
    cout <<ans<<endl;
}

问题 D: 嘉嘉的棋盘游戏

时间限制: 1 Sec  内存限制: 128 MB

题意:

        有国王和刺客阵营,我们为刺客,国王在n*m的棋盘上,我们可以放置多个刺客,每放一次当前刺客距离国王的位置是已知的,求最少放置多少个刺客可以知道国王的位置。

解析:

        如果放在棋盘中间,那么第一次已知距离,国王最多有八种可能,可以发现刺客放在棋盘的角落时,国王最多有四种可能,而且环绕角落周围,且看成一个四分之一圆,那么两个四分之一圆的交点可以唯一确定国王的位置,可以发现最少两个刺客即可确定位置,当然还有特殊情况,棋盘只有一个点时,无需放置刺客,只有一行或者一列时,只需要放置一次。

主要代码:

void solve()
{
    int n,m,ans=0;
    cin >>n>>m;
    if(n==1&&m==1)
    {
        cout <<0<<endl;return ;
    }
    if(n==1||m==1)
    {
        cout <<1<<endl;
    }else{
        cout <<2<<endl;
    }
}

问题 E: 爱丽丝的人偶
时间限制: 1 Sec  内存限制: 128 MB
 

题意:

        有n个人编号从0-n-1,依次循环报数,报到奇数的出列,求第q个离开队伍的人的编号是多少。

解析:

        为方便计算,设编号为1-n,最后答案-1即可。可以发现第一次循环报数出列的为1,3,5,7...(2*i-1)。(i表示当前循环第i位出列的人),第二次:2,6,10,14...(4*i-2),第三次:4,12,20,28...(8*i-4),第四次:...(16*i-8)。可以发现有数学规律,那么我们需要找到在第几层循环出列的人数已经超过q,由数学关系可求得q在当前循环中是第几位出列的,然后由推导公式得到编号,最后减一得到答案。

主要代码:

void solve()
{
    int n,q;
    cin >>n>>q;
    int k=n,res=2,cnt=0;
    while(k)
    {
        int sum=k/2;
        if(k&1) sum++;
        cnt+=sum;
        if(cnt>=q)
        {
            cout <<res*(sum-cnt+q)-res/2-1<<endl;return ; 
        }
        //cout <<cnt<<" "<<res<<endl;
        k/=2;res*=2;
    }
}

问题 F: 遥望远方,答案就在天空的那一端!
时间限制: 1 Sec  内存限制: 128 MB

题意:

        已知当前位置,有n个重力粒子,每踩一次就会跳到与该重力粒子对称的位置,求能跳到最高的高度。

解析:

        看到最高,首先贪心思维,每次踩最低或者最高的粒子,这样可以使向上跳的时候最高,那么就可能有两种策略,下上下上下上...,上下上下上下...,也就是根据粒子个数确定采取何种策略,保证最后一步是上即可,而每次的取法是取最上面那个粒子或者最下面那个粒子,这样可以使得最后高度最高。

主要代码:

void solve()
{
    int n,ans;
    cin >>n>>ans;
    for(int i=1;i<=n;i++)
    {
        cin >>a[i];   
    }
    int l=1,r=n;
    if(n&1)
    {
       for(int i=1;i<=n;i++)
       {
           if(i&1)
           {
              ans=2*a[r--]-ans;
           }else{
              ans=2*a[l++]-ans;
           }
       }
    }else{
        for(int i=1;i<=n;i++)
        {
           if(i&1)
           {
              ans=2*a[l++]-ans;
           }else{
              ans=2*a[r--]-ans;
           }
        }
    }
    cout <<ans<<endl;
}

问题 G: [Ynoi2048] 这里没有数据结构
时间限制: 1 Sec  内存限制: 128 MB 

题意:

        一个倒圆锥上不封顶,一个球,求将球和液体放进圆锥中液体不接触到球的最大体积。

解析:

        数学题,球和圆锥有两种情况,圆锥两边延长线和球相切和相交,那么分两种情况作图,可分别求出两种情况最大体积,那么重点在于如何判断相切或者相交,取极值即可,求恰好与圆锥两边边界相切的球的半径为多少,以此为分界线,判断是否相切。

主要代码:

void solve()
{
    int r,h,R;
    cin >>r>>h>>R;
    if(R<=sqrt(r*r+h*h)*r/h)
    {
       printf("%.2f",acos(-1)*r*r*pow(R*sqrt(r*r+h*h)/r-R,3)/(3*h*h));  
    }else{
       printf("%.2f",acos(-1)*r*r*pow(sqrt(R*R-r*r)+h-R,3)/(3*h*h));    
    }
}

问题 H: 烟花易逝
时间限制: 1 Sec  内存限制: 128 MB

题意:

        这张照片里以某一点(a,b)为中心的烟花最大可能的半径是多少?
半径为R的烟花定义是:所有与中心点的距离小于等于R的点都必须在照片内,对于这些点,将其与在照片内的所有的相邻点比较,离中心点较近的点亮度较大。即当两个在照片中的点(xi,yi),(xj,yj)满足|xi-a|+|yi-b|<=R&&|xj-a|+|yj-b|<=R时,如果|xi-a|+|yi-b|<|xj-a|+|yj-b|且|xi-xj|+|yi-yj|==1,则light(xi,yi)>light(xj,yj)。

解析:

        想到bfs,可以从0-50枚举半径,因为半径不可能超过50,为加快枚举速度可以采取二分查找最大半径,然后对于每一个半径,用bfs判断是否可行,对于每一步,向距离中心点大的前进,而且要满足半径小于当前R,问题在于每一个点需要与距离远的比较大小,如果小于等于则不合题意,而且每一个点只需前进一次即可。

主要代码:

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//#define int long long
#define endl '\n'
#define N  1005
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef unsigned long long ULL;  // 0 ~ 2^64 - 1, 溢出相当于取模
const int inf=0x3f3f3f3f;
const int P=131;   // P 取 131 或 13331 为经验值
const double ex=1e-7;
const int mod=998244353;
int gcd(int a ,int b){ return b ? gcd(b,a%b) : a ;}
typedef pair<int,int>PII;
//priority_queue<int,vector<int>,greater<int> > q;
int n,a[N][N],v[N][N],x,y;
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int bfs(int R)
{
    queue<PII>q;
    q.push({x,y});
    while(q.size())
    {
        PII t=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int l=t.fi+dx[i],r=t.se+dy[i];
            //cout <<l<<" "<<r<<endl;
            if(abs(l-x)+abs(r-y)<=R&&abs(l-x)+abs(r-y)>abs(t.fi-x)+abs(t.se-y))
            {
                if(l<=n&&l>=1&&r<=n&&r>=1)
                {
                    if(a[l][r]>=a[t.fi][t.se])
                    {
                       //cout <<l<<" "<<r<<endl;
                       return 0;
                    }else{
                        //cout <<l<<" "<<r<<endl;
                        if(!v[l][r]) q.push({l,r});
                        v[l][r]=1;
                    }
                }else{
                    //cout <<l<<" "<<r<<endl;
                    return 0;
                }
            }
        }
    }
    return 1;
}
void solve()
{
    int l=1,r=50;
    while(l<r)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                v[i][j]=0;
        int mid=(l+r)/2;
        if(!bfs(mid)) r=mid;
        else l=mid+1;
    }
    cout <<r-1<<endl;
}
int main()
{//ios
    int q;
    cin >>n>>q;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin >>a[i][j];
        }
    }
    while(q--)
    {
        cin >>x>>y;
        solve();
    }
    return 0;
}

问题 I: 亲和数
时间限制: 1 Sec  内存限制: 128 MB

题意:

        两个正整数中,彼此的全部约数之和(本身除外)与另一方相等,则称这两数为亲和数。例如,220和284就互为亲和数。

求1-n中亲和数的个数。

解析:

        关键在于求每个数的真因子和,直接约数枚举显然超时O(n*logn),可以联想到素数筛,一个数的真因子一定小于等于它的一半,故还可以优化。用类素数筛的方法实现O(n*log(logn))的时间复杂度,从而避免超时。

注:如果一个数的真因子的和的真因子的和为它本身,那么他们互为亲和数。

埃氏筛:

void getPrime(int n)
{
    for(int i=2;i<=n;++i)
        isPrime[i] = true;  //假设2-n都是素数
    for(int i=2;i<=n;++i)   //遍历2-n里面所有数
        if(isPrime[i])      //如果i是素数
            //i是素数的话,那么i的倍数肯定就不是合适
            //即 i*2,i*3 .....i*j肯定不是素数,注意边界i*j<=n
            for(int j=i;i*j<=n;++j)
                //n以内,且是i的倍数的数肯定不是素数,设为false
                isPrime[i*j] = false;
}

本题代码:

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define endl '\n'
#define N  1000005
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef unsigned long long ULL;  // 0 ~ 2^64 - 1, 溢出相当于取模
const int inf=0x3f3f3f3f;
const int P=131;   // P 取 131 或 13331 为经验值
const double ex=1e-7;
const int mod=998244353;
int gcd(int a ,int b){ return b ? gcd(b,a%b) : a ;}
typedef pair<int,int>PII;
//priority_queue<int,vector<int>,greater<int> > q;
int n,f[N],m[N];
signed main()
{ios
    for(int i=1;i+i<=N;i++)
    {
        for(int j=2*i;j<=N;j+=i)
        {
            m[j]+=i;
        }
    }
    for(int i=1;i<=N;i++)
    {
        f[i]=f[i-1];
        if(i>m[i]&&m[m[i]]==i)
        {
           f[i]=f[i-1]+1;
           //cout <<m[i]<<" "<<i<<endl;
        }
    }
    while(cin >>n)
    {
        cout <<f[n]<<endl;
    }
    return 0;
}
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值