ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

河南工程学院第五届ACM大学生程序设计竞赛(部分题解)

2021-06-29 10:00:08  阅读:250  来源: 互联网

标签:小明 int 题解 ACM ans 工程学院 include inA 杯子


河南工程学院第五届ACM大学生程序设计竞赛(部分题解)

问题 A: 敏感的小明同学

小明是一个对数字非常敏感的人,当他看到某个特定的数字p (1<=p<=9)时就会兴奋一下,现在给你一个数值区间( l , r ),问你当小明看到这个区间内所有的数字时会兴奋多少下?(例如 l=2,r=22,p=2时,小明会兴奋6下,l=2,12,20,21时各兴奋一下,22兴奋两下)

这道题可以化解为求某个区间中某个数字的个数
举个例子:

12105这个数字,千位上是2,那么千位上出现1的整数有多少个呢?10001999,1100011999,总共是2x1000;(2 = 万位+1)

百位上是1,那么百位上出现1的整数有多少个呢?100-199,1100-1199…9100-9199,10100-10199,…11100-11199,12100-12105,总共是12x100+5+1;

十位上是0,那么十位上出现1的整数有多少个呢?10-19,110-119,210-219…1010-1019…10010-10019…12010-12019…总共:121x10

按照低位、当前位、高位来区分

求【1,N】中1出现的个数规律如下:

如果当前位小于1,那么个数等于高位*当前位率

如果当前位等于1,那么个数等于高位*当前位率 + 低位 + 1
如果当前位大于1,那么个数等于(高位+1)*当前位率

参考网站举个例子:

12105这个数字,千位上是2,那么千位上出现1的整数有多少个呢?10001999,1100011999,总共是2x1000;(2 = 万位+1)

百位上是1,那么百位上出现1的整数有多少个呢?100199,11001199…91009199,1010010199,…1110011199,1210012105,总共是12x100+5+1;

十位上是0,那么十位上出现1的整数有多少个呢?1019,110119,210219…10101019…1001010019…1201012019…总共:121x10

按照低位、当前位、高位来区分

求【1,N】中1出现的个数规律如下:

如果当前位小于1,那么个数等于高位*当前位率

如果当前位等于1,那么个数等于高位*当前位率 + 低位 + 1
如果当前位大于1,那么个数等于(高位+1)*当前位率

参考网站:http://www.voidcn.com/article/p-gswrfywk-qs.html

参考代码

#include<bits/stdc++.h>
using namespace std;
int l,r,p;
int f(int x)
{
    int a=x,t=1,s=0;
    while(x)
    {
        s+=x/10*t;
        if(x%10>p)
        s+=t;
        else if(x%10==p)
        s+=(a%t)+1;//cout<<"1="<<s<<endl;
        x/=10;
        t*=10;
        //cout<<"2="<<s<<endl;
    }
 return s;
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        cin>>l>>r>>p; 
        cout<<f(r)-f(l-1)<<endl;
    }
return 0;
}

问题 B: 森林探险

小明是个方向感极弱的人,为了证明自己,他打算进入森林探险。
他的朋友小红给了他一个写满坐标的地图,如果他按照地图上的点一通过并且最终记住自己向左转动(不包括向后转动)了几次的话,就算小明胜利。
望着地图上密密麻麻的坐标轴,小明头都大了,但是聪明的他立刻想到了你:算法神犇!
你可以帮助他完成这一挑战吗?

问题分析:
这道题可以以平面方程系列中的问题,可以采用点积,叉积的思想解决问题。

向量积,数学中又称外积、叉积,物理中称矢积、叉乘,是一种在向量空间中向量的二元运算。与点积不同,它的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量和垂直。
计算是这样的,对于向量a(x1,y1),b(x2,y2)
他们的叉积a×b=x1y2-y1x2
叉积是一个向量,表示的是有向面积,方向可以用右手定则来判断,比如要用a×b,就要把a旋转到b,如果四指为旋转方向,拇指所指的方向就是叉积的方向

参考链接:
https://blog.csdn.net/ld326/article/details/84689620?utm_source=app&app_version=4.9.1&code=app_1562916241&uLinkId=usr1mkqgl919blen

下面上代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>  //容器
#include<string.h>    //string
#include<math.h>  //数学函数
#include<stack>       //栈
#include<queue>     //优先队列
#include <stdlib.h> //字符串转整形
#include<sstream> //使用istringstrem ( 识别string中的字符串,且不会读取空格)
#include<set>     //set 函数,容器里的元素不能重复
using namespace std;
struct p
{
    int x;
    int y;
}y[2000];
double panduan(p p1,p p2,p p3)
{
    return ((p2.x-p1.x)*(p3.y-p2.y)-(p3.x-p2.x)*(p2.y-p1.y));
}
int main()
{
    int n;
    struct p y[2000];
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>y[i].x>>y[i].y;
    }
    int ans=0;
    for(int i=2;i<n;i++)
    {
        if(panduan(y[i-2],y[i-1],y[i])>0)
            ans++; 
    }
    cout<<ans<<endl;
return 0 ;
}

问题 C: 小明的强迫症

小明是个强迫症患者,每次必须喝固定容量的水,但是森林探险条件简陋,他又忘记携帯量筒,现在找到了据说是算法神犇的你,来帮助他。
他有两个杯子A和B,想要喝的水量C,对杯子A和B可以有三种操作:
1、将杯子 i 满水
2、将杯子 i 的水倒
3、将杯子 i 的水倒进杯子 j 中,在这个操作后,有可能杯子 j 是满的(杯子 i 中可能还有一些水),也有可能杯子 i 是空的(他里面的水都被倒进了杯子 j 里)
为了保持森林探险所需要的体力,对杯子的操作要尽可能的少,现在请你帮助小明,补充水分,使他更好地森林探险。

本题可以用递归进行模拟
先来简化一下这个问题:如果c>a+b,那么我们总可以通过倒入n次a和m次b使得c-(na+mb)<a+b,(n、m为非负整数),所以我们只需要研究c<a+b的情况。设x为a、b两数的最大公约数,那么能够量出c的数学条件是c能整除x,即c%x==0.

因此,在进行判断是否能得到想要的结果后,我们需要分别进行a往b中倒水,然后倒掉b,或者b往a中倒水,然后倒掉a,如此重复,直到符合标准为止。

上代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>  //容器
#include<string.h>    //string
#include<math.h>  //数学函数
#include<stack>       //栈
#include<queue>     //优先队列
#include <stdlib.h> //字符串转整形
#include<sstream> //使用istringstrem ( 识别string中的字符串,且不会读取空格)
#include<set>     //set 函数,容器里的元素不能重复
using namespace std;
         
int daoshui(int A, int B, int C)
{
    int inA = 0;
    int inB = 0;
    int flag = 0;
    int ans=0;
    while(1)   
    {   
        if(flag++>999) 
        {
            ans++;
            break;
        }
        if(0==inA)   
        {   
            ans++;
            inA=A;   
        }   
        else 
        {   
            ans++;
            inB+=inA;   
            if(inB>=B)   
            {    
               inA=inB-B;
               if(C == inA || C == inB)   
                {   
                    return ans;   
                }     
               ans++;
               inB = 0;     
            }   
            else 
            {   
                inA=0;   
            }   
        }    
       if(C == inA || C == inB)   
        {   
            return ans;   
        }   
    }   
}
int main()
{
    int t;  cin>>t;
    while(t--)
    {
        int A,B,C,w;
        cin>>A>>B>>C; 
        if(C%__gcd(A,B)==0)
        {
            int ans1=daoshui(A,B,C);
            int ans2=daoshui(B,A,C);
            cout<<min(ans1,ans2)<<endl;
        }
        else
            cout<<"impossible"<<endl;
}
return 0 ;
}

参考网站:https://blog.csdn.net/henuboy/article/details/11287183?utm_source=blogxgwz1&utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

问题 D: 基建手游

森林探险后小明打算在家中宅一阵子,他迷上了一款基建手游。
在浩瀚的布鲁克西大陆上,有一个神秘的王国,城主小明可以选择在这个王国里圈出一块占地K*K的正方形作为自己的城池,小明希望你选出一块合适的位置,使得他的城池土地价值和最大。

本道题考的知识点为前缀和。

其前缀和的知识点如下:

参考网站:https://blog.csdn.net/K_R_forever/article/details/81775899?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control

在理解前缀和的代码后,我们不难写出代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>  //容器
#include<string.h>    //string
#include<math.h>  //数学函数
#include<stack>       //栈
#include<queue>     //优先队列
#include <stdlib.h> //字符串转整形
#include<sstream> //使用istringstrem ( 识别string中的字符串,且不会读取空格)
#include<set>     //set 函数,容器里的元素不能重复
using namespace std;
int a[1000][1000],b[1000][1000];
int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        {
            cin>>b[i][j];
            a[i][j]=b[i][j]+a[i][j-1]+a[i-1][j]-a[i-1][j-1];
        }
    int max=-999999;
    int x,y;
    k--;
    for(int i=0;i<n-k;i++)
        for(int j=0;j<m-k;j++)
        {
            int sum=a[i+k][j+k]-a[i+k][j-1]-a[i-1][j+k]+a[i-1][j-1];
            if(sum>max)
            {
                x=i+1;
                y=j+1;
                max=sum;
            }
        }
        cout<<x<<" "<<y<<endl;
return 0 ;
}

以上是本次比赛的部分代码,有不对之处,请大家多多交流指正。

标签:小明,int,题解,ACM,ans,工程学院,include,inA,杯子
来源: https://blog.csdn.net/qq_54172129/article/details/118324717

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有