这套题做的一塌糊涂
第一题:组队(5分)
答案:490
——该题真是被难到了,不会编程,感觉用眼找太麻烦,看看分值,就放弃不做了,到最后也没时间做了…
解题流程:
- 必须选够5名编号不同的队员才可以。
- 仔细观察每个队员的信息,会发现,1-5号位有很多人有3项评分都是0,对于这样的人,首先可以关注别的位置的评分能不能被利用上。比如编号为10的选手,3-5位评分都是0,2号位为99,那他就有可能入选2号位的位置,当然还要进行判断。
- 根据步骤2,找队员就省力多了,不过仍旧需细心。
第二题:年号字符(5分)
——没想到进制转化,手算,又错了
答案:BYQ
思路:
——进制转换问题,十进制转二十六进制,但略有一点点不同。
不同之处:
二十六进制余数:0 ~ 25
现在的余数:1 ~ 26
相同之处:
余数的总个数没有变,因此还可以看作进制转化,只是在原来基础上少做改变,请看代码。
代码:
#include<stdio.h>
char a[110];
int main()
{
int i,r,n=2019,cnt=0;
while(n)
{
n--; //无零操作
r=n%26+1; //无零操作
a[++cnt]=r+'A'-1;
n/=26;
}
for(i=cnt;i>=1;i--)
printf("%c",a[i]);
printf("\n");
return 0;
}
第三题:数列求值(10分)
水题公式:(a+b)%m=(a%m+b%m)%m (m=10000)
答案:4659
代码:
#include<stdio.h>
int main()
{
int n=20190324;
int a,b,c,d,i;
a=1,b=1,c=1;
for(i=4;i<=n;i++)
{
d=(a+b+c)%10000;
a=b;
b=c;
c=d;
}
printf("%d\n",d);
return 0;
}
第四题:数的分解(10分)
水题
答案:40785
代码:
#include<stdio.h>
typedef long long ll;
int judge(int n)
{
while(n)
{
if(n%10==4||n%10==2)
return 0;
n/=10;
}
return 1;
}
int main()
{
int a,b,c;
ll ans=0;
for(a=1;a<=2019/3;a++)
{
for(b=a+1;b<=(2019-a)/2;b++)
{
c=2019-a-b;
if(c>b&&a+b+c==2019&&judge(a)&&judge(b)&&judge(c))
ans++;
}
}
printf("%lld\n",ans);
return 0;
}
第五题:迷宫(15分)
注意:下面代码答案是对的,但提交却显示错误,可能是因为该字符串太长了,在编译器的一行内显示不出来完,字符串被自动换行了。
答案:
DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
深搜思路:
- 首先得会深搜模板,该题再加上两个剪枝就能出答案。
- 说说大致思想,利用深搜寻路径,路径用数组a存起来。在搜索过程中会有多条路径,因此再用一个数组b来存放最短的路径。注意:若想得到字典序最短:先搜D,再搜L,再搜右,再搜上。
- 不剪枝,不出结果。
- 剪枝1:当搜索过程中的路径步数step>=最短路径步数minn,就不用再继续搜索下去了,返回。
- 剪枝2:记录每一个点的最短步数dp[tx][ty]=step。因此每当走过一个点时,判断当前步数step与该点的最短步数dp[tx][ty]的大小关系。若step>dp[tx][ty],就返回。因为一定可以通过更短的步数到达这个点。
代码:深搜dfs
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
char e[33][55];
int book[33][55];
int dp[33][55];
int to[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
char p[5]="DLRU";
char a[20200],b[20200];
int n,m,minn;
void dfs(int x,int y,int step)
{
if(step>=minn) //剪枝1
return;
if(x==n&&y==m)
{
minn=step-1;
for(int i=1;i<=step-1;i++)
b[i]=a[i];
b[step]='\0';
return;
}
int tx,ty;
for(int i=0;i<4;i++)
{
tx=x+to[i][0];
ty=y+to[i][1];
if(tx<1||ty<1||tx>n||ty>m)
continue;
if(book[tx][ty]==1||e[tx][ty]=='1')
continue;
if(step>dp[tx][ty]) //剪枝2
continue;
book[tx][ty]=1;
dp[tx][ty]=step;
a[step]=p[i];
dfs(tx,ty,step+1);
book[tx][ty]=0;
}
}
int main()
{
n=30;m=50;minn=INF;
memset(book,0,sizeof(book));
memset(dp,INF,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%s",e[i]+1);
book[1][1]=1;
dfs(1,1,1);
printf("%s\n",b+1);
return 0;
}
广搜思路:
- 广搜基础模板得懂。解决该题只需在结构内再开一个字符数组a来存放路径即可,具体对数组a怎么操作,看下图。
代码:广搜bfs
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
char e[33][55];
int book[33][55];
int to[4][2]={{1,0},{0,-1},{0,1},{-1,0}};
char p[5]="DLRU";
int n,m;
struct Node
{
int x,y,s;
char a[20020];//一定不能开的太小了。
};
void bfs(int x,int y)
{
queue<Node> q;
struct Node u,v;
u.x=x;
u.y=y;
u.s=0;
u.a[0]='s';
q.push(u);
book[x][y]=1;
while(!q.empty())
{
u=q.front();
q.pop();
int i,tx,ty,ts;
for(i=0;i<4;i++)
{
tx=u.x+to[i][0];
ty=u.y+to[i][1];
ts=u.s+1;
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&!book[tx][ty]&&e[tx][ty]=='0')
{
strcpy(v.a,u.a);//继承前一个点的路径。
book[tx][ty]=1;
v.x=tx;
v.y=ty;
v.s=ts;
v.a[ts]=p[i];
q.push(v);
if(tx==n&&ty==m)
{
printf("%s\n",v.a+1);
return;
}
}
}
}
}
int main()
{
n=30;m=50;
memset(book,0,sizeof(book));
for(int i=1;i<=n;i++)
scanf("%s",e[i]+1);
bfs(1,1);
return 0;
}
第六题:特别数的和(15分)
水题,直接上代码
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
int n,i,m,r;
ll sum=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
m=i;
while(m)
{
r=m%10;
if(r==2||r==0||r==1||r==9)
break;
m/=10;
}
if(m!=0)
sum+=i;
}
printf("%lld\n",sum);
return 0;
}
第七题:完全二叉树的权值(20分)
思路:
- 理解什么是完全二叉树,知道父亲结点 i 与儿子结点的关系,左儿子 = 父 * 2,右儿子 = 父 * 2+1。
- 注意最后一行可能不满。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=101000;
ll sum[N];
ll a[N];
int main()
{
int n,i;
scanf("%d",&n);
memset(sum,0,sizeof(sum));
for(i=1;i<=n;i++)
{
scanf("%lld",&sum[i]);
sum[i]+=sum[i-1]; //前缀和
}
int deep=1; //深度
for(i=1;i<=n;i=(2*i+1))
a[deep++]=sum[i]-sum[i/2];
if(n>i/2) //说明最后一行不满
a[deep]=sum[n]-sum[i/2];
else
deep--;
ll maxx=0,xx=1;
for(i=1;i<=deep;i++)
{
if(maxx<a[i])
{
maxx=a[i];
xx=i;
}
}
printf("%lld\n",xx);
return 0;
}
第八题:等差数列(20分)
这位大佬思路:
——题目可以理解为:对于N个数,最少补多少个数可以使这些数成为等差数列,即项数要最小。
——对于升序排列的N个数,首项(a1)和尾项(an)一定是固定的。因为没有必要在第一个数前或最后一个数后再补充数列元素。
——项数 = (an-a1) / d + 1
——公差d越大,项数越小
——有如下两个结论(两者用一个即可):
——公差d一定可以整除数列中每一个数ai减第一个数a1,即:(ai-a1)%d = 0,则公差d最大为(ai-a1)的最大公因数
——公差d一定可以整除数列中每一个数ai减最后一个数an,即:(an-ai)%d = 0,则公差d最大为(an-ai)的最大公因数
——注意:需要特判公差全为0的情况
作者:Vincy_ivy
链接:https://www.jianshu.com/p/08ca0a97f606
来源:简书
大佬的代码我用一下:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100010;
int n,a[maxn];
//这是一个新的球最大公因数的函数~
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
for(int i=2;i<=n;i++)
a[i]-=a[1];
int d=a[2];
for(int i=3;i<=n;i++)
d=gcd(d,a[i]);
//a[n]此时已经是a[n]-a[1]了
if(d)
cout<<a[n]/d+1<<endl;
else
cout<<n<<endl;
return 0;
}