您的位置:首页 > 其它

《TC训练赛一》题解!

2016-10-17 15:11 120 查看
 以下题目标题就是此题题目链接,题目内容为了节省篇幅就不粘上去了。整套题的链接:https://acm.bnu.edu.cn/v3/contest_show.php?cid=8679#info 密码:7116

                                                        A. 进制转换

  题意很明显,就不过多说明了。

  此题需要注意的是n为32位整数,即int型,最好特判一下n为0的情况;还有如果n为负数,要提前输出一个负号。最后输出的时候逆着输出来,可以手动模拟一下二进制的转化过程。

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<functional>
using  namespace std;
typedef long long LL;
#define pi 3.141592653
const int INF=1e9;
//const int N=100000+10;
char f[6]={'A','B','C','D','E','F'};//给定的R<=16,16进制到f就可以了;
char b[35];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(n<0)
{
printf("-");
n=-n;//将其转化为正数便于求解;
}
if(n==0)
{
printf("0\n");
continue;//直接进入下一层循环,不会继续往下执行了;
}
int len=0;//表示数组长度;
while(n)//这里也可以写成while(n!=0)
{
int x=n%m;
if(x<10)
b[len++]=x+'0';//加'0'表示转化成char型,可以查查ASCII表看看他们之间的关系;
else b[len++]=f[x-10];
n/=m;
}
for(int i=len-1;i>=0;i--)//注意要倒着输出;
printf("%c",b[i]);//只接了一条语句可以不用加中括号;
printf("\n");
}
}//每一条语句都是一个知识点,基础抓牢了才能更进一步!


                                                     B. 桌球游戏       

  题意很好懂,台面上剩余的球可得的分数R如果小于他们两个人的分差,那么分数小的即使把剩下的球全打进了也无济于事。注意分差为正数,这里就可以用abs()函数了,不会的自己百度去~~~
int main()//为了节省篇幅以上的头文件我就不贴出来了;
{
int t,a,b,r;//用a来表示SA选手的得分,
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&a,&b,&r);
if(abs(a-b)>r) printf("yes\n");
else printf("no\n");//只有两种情况
}
return 0;
}//代码是不是很简洁啊,多多刷题你也可以的!


                                                       C. 密码

     题意就是给你一个长度最多为50的字符串,字符类型只可能是那四类中的某一种,有两个判断条件,一是判长度符不符合8~16,二是判断这个字符串的所有字符至少有三种来自不同的类型,以上都满足则输出YES,输出的时候注意输出题目所给的,不要自己打成yes,Yes,No之类的,你完全可以复制题目所给的输出放到你的输出语句里。
    代码 一:
char s[55];//最大长度为50,数组空间应该稍微开大一点;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
int f1=0,f2=0,f3=0,f4=0;
int len=strlen(s);//此函数用来测字符串长度,书的144页,很实用。
if(len<8||len>16)
{
printf("NO\n");
continue;
}
else
{
for(int i=0;i<len;i++)//字符型数组是从0开始的到len-1正好len的长度;
{
if(s[i]>='A'&&s[i]<='Z') f1=1;//满足条件则将此变量赋为1表示真;
else if(s[i]>='a'&&s[i]<='z') f2=1;
else if(s[i]>='0'&&s[i]<='9') f3=1;
else f4=1;
}
if(f1+f2+f3+f4>=3)//至少满足4种字符里的3种;
printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
         代码二:
char s[55];//最大长度为50,数组空间应该稍微开大一点;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
int f1=0,f2=0,f3=0,f4=0;
int i;
for(i=0; s[i]!='\0'; i++) //字符串以'\0'结束,不计入总长度;
{
if(s[i]>='A'&&s[i]<='Z') f1=1;
else if(s[i]>='a'&&s[i]<='z') f2=1;
else if(s[i]>='0'&&s[i]<='9') f3=1;
else f4=1;//满足条件则将此变量赋为1表示真;
}
if((i<8||i>16)||(f1+f2+f3+f4<3))
printf("NO\n");
else printf("YES\n");
}
return 0;
}


 
                                                    D. box

        题意就是给定三个整数,要你判断用+ ,- ,* ,/ ,% ,是否能把这三个数联系起来!
        需要注意的就是题目并没有说数的范围,所以应该用long long型,还有只需判断+,*,%即可。除法这里有点小问题,用乘法更为保险。
        代码一:
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<functional>
using  namespace std;
typedef long long LL;
#define pi 3.141592653
const int INF=1e9;
int judge(long long x,long long y,long long z)
{
if(x+y==z) return 1;//return语句是整个函数的结束标志;
if(y!=0&&x%y==z) return 1;
if(x*y==z) return 1;
return 0;//以上都不符合则返回0表示假;
}
int main()
{
long long a,b,c;
while(~scanf("%I64d%I64d%I64d",&a,&b,&c))
{
int x1=judge(a,b,c);
int x2=judge(a,c,b);
int x3=judge(b,a,c);
int x4=judge(b,c,a);
int x5=judge(c,a,b);
int x6=judge(c,b,a);
if(x1||x2||x3||x4||x5||x6)//任何一种为真都可以;
printf("oh,lucky!\n");
else printf("what a pity!\n");
}
return 0;
}


        代码二:
int main()
{
long long a,b,c;
while(~scanf("%I64d%I64d%I64d",&a,&b,&c))
{
if(a+b==c||a+c==b||a-c==b||a*b==c||a-b==c||c*a==b||c*b==a||(b!=0&&(a%b==c||c%b==a))||(a!=0&&(c%a==b||b%a==c))||(c!=0&&(a%c==b||b%c==a)))
printf("oh,lucky!\n");
else printf("what a pity!\n");
}
return 0;
}


                                                       E. 整数解

         讲道理这个题应该都会的,就是一个解方程。判断有无整数解即可。如果你不会判断整数解,那就判断这个解是否满足所给出的条件。
        代码一:由于此题数据范围不是很大,可以采用暴力枚举的方法求解。
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
int flag=0;
for(int i=-9999;i<=9999;i++)
{
if(i*(n-i)==m)
{
flag=1;
break;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}


       代码二:用求根公式判断有无整数解。
#include<stdio.h>
#include<math.h>
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
double b1=(n+sqrt(n*n-4*m))/2;
double b2=(n-sqrt(n*n-4*m))/2;
if((int)b1==b1||(int)b2==b2)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}


       代码三:判断是否符合条件。
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<functional>
using  namespace std;
typedef long long LL;
#define pi 3.141592653
const int INF=1e9;
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
int temp=n*n-4*m;//求根公式;
if(temp<0)
{
printf("No\n");
continue;
}
int x1=(n-(int)sqrt(temp))/2;
int x2=(n+(int)sqrt(temp))/2;
if(x1*(n-x1)==m||x2*(n-x2)==m)//判断是否符合条件;
printf("Yes\n");
else printf("No\n");
}
return 0;
}


                                                  F. 矩形A + B

        题意给你两个数表示网格的高和宽,图片可能加载不出来,原图:


        这是一个2X4的网格,问里面有多少个矩形。很明显上图有30个。

        那么怎么做呢,我们观察发现一个小矩形有两条横线和两条竖线(提示到这了,还不会就说不过去。 。。。)这就是一个组合问题嘛,总共n+1条横线,m+1条竖线。随便选两条都可以组成一个矩形。。

int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
printf("%d\n",(n+1)*n/2*(m+1)*m/2);
}
return 0;
}


                                                  G. 第二小整数

       这道题考的就是一个排序问题,排好序后直接输出第二个数即可。可以用冒泡排序、选择排序、sort()函数。

       代码一:sort()函数,此函数默认从小到大排序。
int a[15];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
printf("%d\n",a[1]);//下标从0开始所以a[1]是第二个;
}
return 0;
}


       代码二:冒泡排序:
int a[15];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
{
for(int j=0;j<n-i-1;j++)
if(a[j]>a[j+1])
swap(a[j],a[j+1]);
}
printf("%d\n",a[1]);
}
return 0;
}


                                                 H. 分拆素数和

      给你并不是很大的整数问你将这个数拆分成不同的素数相加有多少种方法。
      那这题考察的就是一个素数判定问题。有两种方法:
      代码一:必须掌握
int judge(int x)
{
for(int i=2;i<=sqrt(x);i++)
if(x%i==0) return 0;
return 1;
}
int main()
{
int n;
while(~scanf("%d",&n)&&n)//这里也可以写成 &&n!=0
{
int ans=0;//注意每组数据的答案都要先初始化;
for(int i=2;i<=n/2;i++)
if(judge(i)&&judge(n-i)&&2*i!=n)//注意是不同的素数和;
ans++;
printf("%d\n",ans);
}
return 0;
}


       代码二:要求有点高,不过可以尝试理解
void init()//素数预处理打表便于查询;
{
memset(a,-1,sizeof(a));
a[0]=a[1]=0;
for(int i=2; i<N; i++)
if(a[i])
{
if(i>N/i) continue;
for(int j=i*i; j<N; j+=i)
a[j]=0;
}
}
int main()
{
init();
int n;
while(~scanf("%d",&n)&&n)
{
int ans=0;
for(int i=2; i<=n/2; i++)
if(a[i]&&a[n-i]&&i*2!=n)
ans++;
printf("%d\n",ans);
}
return 0;
}


                                                         I. 分数矩阵
       样例基本上可以解释题意了,就问你怎么求出这个分数矩阵的值了。

       其实仔细观察可以发现这是一个规律题的,找规律就好了。

int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
double ans=0;
for(int i=1;i<=n;i++)
{
if(i==1) ans+=n;
else ans+=2.0*(n-i+1)/i;
}
printf("%.2lf\n",ans);
}
return 0;
}


         

                                             
J. 最大公约数与最小公倍数

             国庆的题的水平,用来签到的。最小公倍数等于两数之积除以最大公约数。用辗转相除法求最大公约数。也可以用递归求解,原理类似。

             代码一:
int gcd(int a,int b)
{
while(b)
{
int c=a%b;
a=b;
b=c;
}
return a;
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int max_factor=gcd(n,m);
int min_dev=n*m/max_factor;
printf("%d %d\n",max_factor,min_dev);
}
return 0;
}

       代码二:递归
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int max_factor=gcd(n,m);
int min_dev=n*m/max_factor;
printf("%d %d\n",max_factor,min_dev);
}
return 0;
}


       终于写到最后一题了。。。。。。。。。。。

                                                     K. 奇偶位互换           
                所给的字符串已知长度是偶数,设为len,但字符数组下标从0开始,故最后一位len-1为奇数,len-2为偶数;要实现奇偶位互换,只需当遇到偶数位时先将后一位输出,再输出这一位。

char a[55];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",a);
int len=strlen(a);
for(int i=0;i<len;i++)
if(i%2==0)
{
printf("%c%c",a[i+1],a[i]);
}
printf("\n");
}
return 0;
}

   

         本场联系题的全部题解呈上。本来这套题要给大家用来做周赛的,不过遇到点小问题,所以。。。。但如果大家把这套题吃透了,,,说明大家的水平又上了一级。希望大家认真对待。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: