概述
感觉都是正常想就能写出来的题 我的过提顺序是ABCED(没错就写了五题) 这也是刚学半年C的小筎蒻第一次写文章 有什么意见和改进方向尽管提喵
A 数字回文
题目
有一个字符串中嵌入了 1~9 的数字,字符串中包含的字符个数小于 10,且字符不为空 格、制表符等空白字符。请从左到右取出这些数字组成一个新的数字字符串,然后判断该 数字字符串是否为回文?如果是回文,输出“Yes”,否则输出“No”。
思路
就是取数字字符出来放到一个新字符串里然后判断回文 直接写也不会爆 签到题 上代码
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char s[20],a[20];
scanf("%s",s);
int n=strlen(s);
int j=0;
for(int i=0; i<n; i++)
{
if(isdigit(s[i]))
{
a[j]=s[i];
j++;
}
}
int flag=1;
for(int i=0; i<=j/2; i++)
{
if(a[i]!=a[j-1-i])
{
flag=0;
break;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
吐槽
一开始样例上写的YES和NO都是大写但是数据点里都是小写 我因为这个错了一次 刚交完就通知说第一题题面有错误让刷新
还有就是我把isdigit打成isalpha错了半天找不到问题在哪
B 质数串
题目
从 2 开始的质数如下: 2 3 5 7 11 13…… 如果将质数按顺序合并为一个长长的数字串就得到: 23571113…… 现在问这个串第 n 个数字是什么?以及该数字来源于哪一个质数?
思路
提前写俩数组 a[n]存第n个数来自哪个素数 b[n]存第n个数是啥数 直接在读入case之前搞定 姑且有点个dp的感觉 注意循环次数 容易爆 题目的数据刚好卡在要超时的临界位置
代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int isPrime(int a)//因为我从2开始遍历所以就懒得对1加判断了
{
if(a==2)
return 1;
for(int i=2;i<=sqrt(a);i++)
{
if(a%i==0)
return 0;
}
return 1;
}
int main()
{
int a[100010],b[100010];
int i=1;
for(int num=2;i<=100010;num++)
{
if(isPrime(num))
{
int time=1;//time是倍数的意思 不是时间!
while(time<num)
time*=10;
time/=10;
int now=num;
while(now>0)
{
a[i]=num;
b[i]=now/time;
now=now%time;
time/=10;
i++;
}
}
}
int T;
scanf("%d",&T);
while(T--)
{
int haohaohao;
scanf("%d",&haohaohao);
printf("%d %d\n",b[haohaohao],a[haohaohao]);
}
return 0;
}
吐槽
那道题先兴高采烈地把下面的读取输入写好的 为了防止写忘了把字母重复利用了所以写了个巨长的 只能说好好好
C 测试科拉茨猜想
题目
著名的科拉茨猜想提出:任取一个正整数,如果这个数是偶数,则除以 2。如果是奇数, 乘以 3 再加 1。结算结果重复上述步骤,最后起始数都会变成 1。 科拉茨猜想看起来十分简单,但是证明却无从下手。现在邀请大家编程检验一百万以内的 正整数的科拉茨猜想是否成立,如果给定的正整数最后会变成 1,请给出计算的次数(称为 正整数的科拉茨计算次数);如果不能变成 1,返回-1。 例如:正整数 3 的科拉茨计算次数为 7:3->10->5->16->8->4->2->1。
思路
最简单的一题 while(1)计数到1就break就完事了 我当时也是这么写的 现在想看看能不能用递归实现一下子
代码
循环版
#include <stdio.h>
#include <stdlib.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int a;
scanf("%d",&a);
int count=0;
while(1)
{
if(a==1)
break;
if(a%2==0)
a/=2;
else
a=a*3+1;
count++;
}
printf("%d\n",count);
}
return 0;
}
递归版
#include <stdio.h>
#include <stdlib.h>
int f(int a)
{
if(a==1)
return 0;
if(a%2==0)
return f(a/2)+1;
return f(a*3+1)+1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int a;
scanf("%d",&a);
printf("%d\n",f(a));
}
return 0;
}
D 输出球队的名次
题目
描述
甲、乙、丙三位球迷分别预测已进入半决赛的四队 A、B、C、D 的名次如下:
甲预测:A 第 1 名,B 第 2 名;
乙预测:C 第 1 名,D 第 3 名;
丙预测:D 第 2 名,A 第 3 名。
比赛结果,甲、乙、丙预测各对一半。试求 A、B、C、D 四队名次,如果能求出,那么输 出它们的名次,可能不止一种情况(按 a,b,c,d,名次数小的先排先输出);否则输 出“No”。
输入格式
多组 Case,读入到文件末尾结束 每组 Case 一行 6 个数,按甲、乙、丙顺序,输入他们的预测名次用整数 1~4,用空格分隔。
输出格式
每个 Case: 按 A、B、C、D 的顺序输出它们的名次,按字典序从小到大输出所有可能。
输入样例
1 2 1 3 2 3
1 2 1 2 1 2
输出样例
a=3,b=2,c=1,d=4
No
思路
一开始我感觉遍历的话情况太多算不过来(我现在自己听我这想法我都觉得蠢) 于是按人脑想法开始模拟 发现代码好长情况好多懒得打 而且搞完了我还得排字典序 回过头来才发现遍历轻松杀 那还说啥啊 都浪费那么多时间了 赶紧写就完事了 上代码
特别注意:每人的猜测都对一半说明一个猜测是对的而另一个猜测一定是错的
代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
while(1)
{
int a1,b1,c2,d2,d3,a3;
scanf("%d%d%d%d%d%d",&a1,&b1,&c2,&d2,&d3,&a3);
int flag=1;//这个是判断我要不要输出No的
for(int a=1;a<=4;a++)
{
for(int b=1;b<=4;b++)
{
for(int c=1;c<=4;c++)
{
for(int d=1;d<=4;d++)
{
if(a==b||a==c||a==d||b==c||b==d||c==d)
continue;//四个球队的名次肯定不会有重复对伐
//下面是主体喵
if(a==a1&&c==c2&&d==d3&&b!=b1&&d!=d2&&a!=a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
if(a!=a1&&c==c2&&d==d3&&b==b1&&d!=d2&&a!=a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
if(a==a1&&c!=c2&&d==d3&&b!=b1&&d==d2&&a!=a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
if(a==a1&&c==c2&&d!=d3&&b!=b1&&d!=d2&&a==a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
if(a!=a1&&c!=c2&&d==d3&&b==b1&&d==d2&&a!=a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
if(a==a1&&c!=c2&&d!=d3&&b!=b1&&d==d2&&a==a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
if(a!=a1&&c==c2&&d!=d3&&b==b1&&d!=d2&&a==a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
if(a!=a1&&c!=c2&&d!=d3&&b==b1&&d==d2&&a==a3){
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);flag=0;continue;}
}
}
}
}
if(flag)
printf("No\n");
}
return 0;
}
吐槽
那个文件输入直到结束我是真搞不来 一直搞EOF啥的发现总是会把最后一个case无限输出 最后直接写while(1)反而可以了 这一段我是真搞不明白
因为flag是后加的嘛 当时加的时候直接写在continue后面了 所以无论如何最后总是会多输出一个No 就这么个玩意儿我找了半天 靠
E 圆和矩形是否有重叠
题目
给定以 (r, x, y) 表示的圆和一个与坐标轴平行的矩形 (x1, y1, x2, y2),其中 r 是圆 的半径长度, x, y 是圆心的坐标; (x1, y1) 是矩形左下角的坐标,而 (x2, y2) 是右上 角的坐标。
如果圆和矩形有重叠的部分,请返回 1 ,否则返回 0 。
注意,请检测是否存在点 (xi, yi),它既在圆上也在矩形上(两者都包括点落在边界上的情况)。
举例 1:
输入:r = 1, x = 0, y = 0, x1 = 1, y1 = -1, x2 = 3, y2 = 1
输出:1
解释:圆和矩形存在公共点 (1,0) 。
举例 2:
输入:r = 1, x = 1, y = 1, x1 = 1, y1 = -3, x2 = 2, y2 = -1
输出:0
思路
最最最最最一开始没想什么数学方式 咱们直接遍历 就写成了这个样子
#include <stdio.h>
#include <stdlib.h>
long long max(long long a,long long b)
{
if(a>=b)
return a;
else
return b;
}
long long min(long long a,long long b)
{
if(a>=b)
return b;
else
return a;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
long long r,x,y,x1,y1,x2,y2;
scanf("%lld%lld%lld%lld%lld%lld%lld",&r,&x,&y,&x1,&y1,&x2,&y2);
long long shang=max(y+r,y2),xia=min(y-r,y1),zuo=min(x-r,x1),you=max(x+r,x2);
int isBreak=0;
for(long long i=zuo;i<=you;i++)
{
for(long long j=xia;j<=shang;j++)
{
if((x-i)*(x-i)+(y-j)*(y-j)<=r*r&&i>=x1&&i<=x2&&j>=y1&&j<=y2)
{
isBreak=1;
break;
}
}
if(isBreak)
break;
}
printf("%d\n",isBreak);
}
return 0;
}
结果发现TLE了喵(当然样例数据是能跑出来的 你可以试试)
那就改呗 开始研究数学
一开始我想的是比较复杂的 用了各种各样的表达式 加了一堆if判断 就是满足这些条件就可以认定这个圆和矩形有重叠使得flag=1喵 但是永远无法概括出所有的情况 总是会错误
这个时候我们不妨反其道而行之 默认是能重叠 满足一些条件就不能重叠 再让flag=0
这样就很好想了:如果圆的最下面一个点都在矩形上方 那应该就肯定不重叠了喵 其他三个方向也是同理
很好 那我们就开始写吧
#include <stdio.h>
#include <stdlib.h>
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
long long r,x,y,x1,y1,x2,y2;
scanf("%lld%lld%lld%lld%lld%lld%lld",&r,&x,&y,&x1,&y1,&x2,&y2);
int flag=1;
if(x+r<x1)
flag=0;
else if(x-r>x2)
flag=0;
else if(y-r>y2)
flag=0;
else if(y+r<y1)
flag=0;
printf("%d\n",flag);
}
return 0;
}
很好 样例测试一下也能过 自信提交! “错误”!
那我们再仔细地想一想 是不是有这样一种情况 在上面的判断中会是有重叠 但是实际上并没有
所以嘛 我们还要对矩形的顶点加判断
#include <stdio.h>
#include <stdlib.h>
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
long long r,x,y,x1,y1,x2,y2;
scanf("%lld%lld%lld%lld%lld%lld%lld",&r,&x,&y,&x1,&y1,&x2,&y2);
int flag=1;
if(x+r<x1)
flag=0;
else if(x-r>x2)
flag=0;
else if(y-r>y2)
flag=0;
else if(y+r<y1)
flag=0;
if((x-x1)*(x-x1)+(y-y1)*(y-y1)>r*r)
flag=0;
else if((x-x1)*(x-x1)+(y-y2)*(y-y2)>r*r)
flag=0;
else if((x-x2)*(x-x2)+(y-y1)*(y-y1)>r*r)
flag=0;
else if((x-x2)*(x-x2)+(y-y2)*(y-y2)>r*r)
flag=0;
printf("%d\n",flag);
}
return 0;
}
OK再测试一下 这次发现连样例都过不了了 出大问题
发现判断顶点有一个前提 就是我的圆心得在左上/左下/右上/右下角 如果圆心在侧面那完全有可能是别的情况让我有重叠
最后改一下提交就过了喵
代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
long long r,x,y,x1,y1,x2,y2;
scanf("%lld%lld%lld%lld%lld%lld%lld",&r,&x,&y,&x1,&y1,&x2,&y2);
int flag=1;
if(x+r<x1)
flag=0;
else if(x-r>x2)
flag=0;
else if(y-r>y2)
flag=0;
else if(y+r<y1)
flag=0;
if((x-x1)*(x-x1)+(y-y1)*(y-y1)>r*r&&x<x1&&y<y1)
flag=0;
else if((x-x1)*(x-x1)+(y-y2)*(y-y2)>r*r&&x<x1&&y>y2)
flag=0;
else if((x-x2)*(x-x2)+(y-y1)*(y-y1)>r*r&&x>x2&&y<y1)
flag=0;
else if((x-x2)*(x-x2)+(y-y2)*(y-y2)>r*r&&x>x2&&y>y2)
flag=0;
printf("%d\n",flag);
}
return 0;
}
总结
OK那以上就是我的第一篇文章 希望能对你有所帮助(感觉也只帮助得到大一的新生哈)
后面的题应该会有转载官方题解的吧 我这就是个个人向记录而已
在可能会有的下一篇文章再见喵~