表示这比赛坑好多……
咳,总之在各种特殊的wa姿势之间摸爬滚打终于完成了这8道题……
题解时间到~
A 最小公倍数
求 a1 , a2 ,…, an 共n个数的最小公倍数。
关键:若x是 a1 , a2 ,…, an−1 的最小公倍数,则 a1 , ,a2 ,…, an 的最小公倍数为 anxgcd(x,an) (注意实际实现中先除后乘,否则有可能爆范围)。
#include <cstdio>
using namespace std;
typedef unsigned int u32;
u32 gcd(u32 a,u32 b){return b?gcd(b,a%b):a;}
int main(){
int t,n;
u32 tmp,ans;
int i,j;
scanf("%d",&t);
for(i=0;i<t;i++){
scanf("%d",&n);
ans=1;
for(j=0;j<n;j++){
scanf("%u",&tmp);
ans*=tmp/gcd(ans,tmp);
}
printf("%u\n",ans);
}
return 0;
}
B 进制转换
输入一个十进制整数n,输出它的r进制表示形式。
解法:连除取余,倒序输出。
原理:
n=a0r0+a1r1+a2r2+...+anrn
技巧:此题输入有多组数据,且题目未给出数据组数,开始我用feof(stdin)
来判断是否已读到文件末尾,但貌似在win下不灵(渣渣ms还我罚时!)……最后在出题人主办方建议下改成了scanf(...)==EOF
来判断……
注意:有负数,而且至少在我见过的代码中输入为0的情况都要特判。
#include <cstdio>
typedef long long ll;
char str[64];
int main(){
ll n;
int r;
int i;
while(!feof(stdin)){
scanf("%I64d%d",&n,&r);
if(n==0)printf("0\n");
else{
if(n<0){
putchar('-');
n=-n;
}
for(i=0;n;i++){
str[i]=n%r;
n/=r;
}
for(i--;i>=0;i--)
putchar((str[i]>9)?(str[i]-10+'A'):str[i]+'0');
putchar('\n');
}
}
return 0;
}
C 三角形
输入三个正数问能否以这三个数为三边长组成三角形。
知识:小学算术。
#include <cstdio>
#include <algorithm>
using namespace std;
double l[3];
int main(){
int m;
int i,j;
scanf("%d",&m);
for(i=0;i<m;i++){
for(j=0;j<3;j++)
scanf("%lf",l+j);
sort(l,l+3);
printf((l[0]+l[1]>l[2])?"YES\n":"NO\n");
}
return 0;
}
D 空心三角形
输入一个三角形的高,在输出中绘制出这个三角形。
经验:一个高为
h
的三角形底边长为
(不是很复杂的实现题我一般不会出问题……)
#include <cstdio>
using namespace std;
char str[10];
int main(){
int n;
bool b=false;
char c;
int i,j;
while(true){
scanf("%s",str);
c=str[0];
if(c=='@')break;
if(b)putchar('\n');
scanf("%d",&n);
for(i=1;i<=n;i++){
for(j=i;j<n;j++)putchar(' ');
putchar(c);
if(i==1){
putchar('\n');
}else if(i==n){
for(j=2;j<n*2;j++)putchar(c);
putchar('\n');
}else{
for(j=3;j<i*2;j++)putchar(' ');
putchar(c);
putchar('\n');
}
}
b=true;
}
return 0;
}
E 整数解
输入两个整数n和m,问方程组
是否至少有一组整数解……
解法1:枚举
x∈[−|m|,|m|]
,则
y=n−x
,判断
xy=m
是否成立即可。
解法2:
由
得
代入 x+y=n 中得
即
然后利用一元二次方程求根公式即可。(正在码……)
注意:”Yes”和”No”!
#include <cstdio>
#include <cmath>
using namespace std;
int main(){
int n,m;
int absm;
bool b;
int i;
while(true){
scanf("%d%d",&n,&m);
if((!n)&&(!m))return 0;
b=false;
absm=abs(m);
for(i=-absm;i<=absm;i++){
if(abs(n-i)>absm)continue;
if(i*(n-i)==m){
printf("Yes\n");
b=true;
break;
}
}
if(!b)printf("No\n");
}
return 0;
}
F 考试排名
典型毒瘤手写ms word题……(出题人呢?出来出来……)
技巧:scanf()返回值为成功输入的数据个数(,然后你就知道括号怎么办了吧……)
注意:排序先按ac数降序,ac数相同再按时间分升序,都相同再按名字字典序升序……(大于小于别搞反)
吐槽:你妹滴题目明明没有说明最大学生数量,害我wa了四次!(出题人还我罚时!)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
struct stu{
int ac;
double grade;
char name[20];
};
stu stus[1000];
char str[100];
bool cmp(const stu& a,const stu& b){
if(a.ac==b.ac)
if(a.grade==b.grade)
return strcmp(a.name,b.name)<0;
else return a.grade<b.grade;
else return a.ac>b.ac;
}
void rp(char *s,int n){
int len=strlen(s);
int i;
for(i=0;i<n-len;i++)putchar(' ');
printf(s);
}
int main(){
int n,nstu;
double m;
double ta;
int tb;
int num,len;
int tmp;
int i,j;
//freopen("d1t6.in","r",stdin);
//freopen("d1t6.out","w",stdout);
scanf("%d%lf",&n,&m);
for(i=0;true;i++){
if(scanf("%s",stus[i].name)==EOF)goto output;
for(j=0;j<n;j++){
num=scanf("%lf(%d)",&ta,&tb);
//printf("%d %d %d\n",num,ta,tb);
if(num==1){
if(ta>0){
stus[i].ac++;
stus[i].grade+=ta;
}
}else{
stus[i].ac++;
stus[i].grade+=ta+tb*m;
}
}
}
output:
nstu=i;
sort(stus,stus+nstu,cmp);
//printf("%d\n",nstu);
for(i=0;i<nstu;i++){
printf("%s",stus[i].name);
len=strlen(stus[i].name);
for(j=0;j<11-len;j++)putchar(' ');
sprintf(str,"%d",stus[i].ac);
rp(str,2);
putchar(' ');
if(floor(stus[i].grade)!=stus[i].grade)5/0;
sprintf(str,"%d",tmp=stus[i].grade);
rp(str,4);
//putchar(' ');
putchar('\n');
}
return 0;
}
G Olympiad
定义各位数字互不相同的数为美丽的数(美个头!),输入若干组
a,b
,问
[a,b]
内美丽的数的个数……
解法:
定义
an={0,1,n丑,n美,
,则问题可转化为求
{an}
的前n项和
{Sn}
,继而使用记忆前缀和的方法求解。
#include <cstdio>
#define BMAX 100000
bool mp[10];
int s[BMAX+1];
bool isbeaut(int num){
int i;
for(i=0;i<10;i++)mp[i]=false;
for(;num;num/=10)
if(mp[num%10])return false;
else mp[num%10]=true;
return true;
}
int main(){
int t;
int ta,tb;
int i,j;
for(i=1;i<=BMAX;i++)
s[i]=s[i-1]+isbeaut(i);
scanf("%d",&t);
for(i=0;i<t;i++){
scanf("%d%d",&ta,&tb);
printf("%d\n",s[tb]-s[ta-1]);
}
return 0;
}
H 鸡兔同笼
现有若干只鸡与若干只兔关在同一笼中,输入鸡和兔脚的总数n,求笼中鸡和兔总只数的最小值和最大值。
思想:类似于贪心
解法:若求最小值,则令笼中兔的数量尽可能多(有可能剩余两只脚,为鸡脚);反之若求总只数最大值,则令笼中全为鸡即可。
注意:看清题!差点以为是小学奥数解方程题……
#include <cstdio>
int main(){
int a;
int i;
scanf("%d",&a);
if(a%2)printf("0 0\n");
else printf("%d %d\n",a/4+!!(a%4),a/2);
return 0;
}
尾声
感受了一下acm的气氛,竞争还是很激烈的……切记就算所有题都会做也马虎不得……