本文代码均省略库和namespace声明,其中read()函数是读入数值的函数。
A 中间数
从标准输入设备读入三个整数a、b、c,找出中间数并输出。 中间数定义为: 若三数不相等,则第2大的数是中间数;若有两个数相等,则最大数作为中间数。
对应每一组测试数据,输出其中间数。
确实水,但是需要注意题目对中间数的定义,不要想当然地直接输出第二大的数……
int a,b,c,T;
int main()
{
for(read(T);T;--T)
{
read(a); read(b); read(c);
if(a>b) swap(a,b);
if(b>c) swap(b,c);
if(a>b) swap(a,b); // 手动排序
printf("%d\n",(a==b||b==c)?c:b);
}
return 0;
}
B 跳水打分问题
运动员跳水时,有n个评委打分,分数为10分制,且有两位小数。得分规则为:去掉最高分和最低分,求剩下分数的平均值,就是运动员的最终得分。
有多组测试数据。第一行是整数T (T <= 100),表示测试数据的组数,随后有T组测试数据。每一组测试数据占一行,分别为整数n和n个评委的打分,相邻数之间有一个空格。其中,2<n≤100。
对应每组输入,输出该运动员的得分,保留2位小数。
按题意模拟即可。
int n,T;
double sco[101],sum;
int main()
{
for(read(T);T;--T)
{
read(n);
sum=0;
for (register int i=1;i<=n;++i) scanf("%lf",&sco[i]),sum+=sco[i];
sort(sco+1,sco+n+1);
sum-=sco[1]+sco[n];
printf("%.2lf\n",sum/double(n-2));
}
return 0;
}
C 最大公约数与最小公倍数
从标准输入设备读入两个正整数,求两数的最大公约数与最小公倍数。
有多组测试数据。输入的第一行是整数T(0<T≤100),表示测试数据的组数。每一组测试数据只有一行,分别为整数a和b,两数之间有一个空格。0<a,b≤32767。
对应每组输入,输出一行对应两数的最大公约数和最小公倍数,两数之间用一个空格隔开。
按题意模拟即可。注意 a*b=lcm(a,b)*gcd(a,b) 。
int T,x,y,g;
int gcd(int a,int b) {return b?gcd(b,a%b):a;}
int main()
{
for(read(T);T;--T)
{
read(x); read(y);
g=gcd(x,y);
printf("%d %d\n",g,x/g*y);
}
return 0;
}
D 分数运算
读入4个整数a、b、c、d和一个运算符(‘+’、‘-’、‘*’、‘/’中的一个),进行分数a/b和c/d的对应运算,输出最简结果。
有多组测试数据。输入的第一行是整数T(1<=T<=200),表示随后测试数据的组数。每组测试数据占一行,由四个正整数a,b,c,d和一个运算符组成,相邻数据间有一个空格。
对应每组测试数据,输出分数运算的最简结果,占一行。具体可参照样例。
注意输出格式,不是只输出结果,而是要输出算式。
int T,a,b,c,d,ansa,ansb,g;
char y;
inline int abs(int x) { return x<0?-x:x; }
int gcd(int i,int v) {return v?gcd(v,i%v):i;}
int main()
{
for(read(T);T;--T)
{
read(a); read(b); read(c); read(d);
y=getchar();
switch(y)
{
case '+': ansa=a*d+b*c; ansb=b*d; break;
case '-': ansa=a*d-b*c; ansb=b*d; break;
case '*': ansa=a*c; ansb=b*d; break;
case '/': ansa=a*d; ansb=b*c; break;
}
do{ g=gcd(abs(ansa),ansb); ansa/=g; ansb/=g; }while(g>1);
if(ansb==1) printf("%d/%d%c%d/%d=%d\n",a,b,y,c,d,ansa);
else printf("%d/%d%c%d/%d=%d/%d\n",a,b,y,c,d,ansa,ansb);
}
return 0;
}
E 排列问题
读入两个非负大整数,判断其中一个是否能由另一个大整数内的数字重新排列得到。
有多组测试数据。输入的第一行是整数T(1<=T<=200),表示随后有T组测试数据。每组测试数据占两行,每行是一个非负大整数,位数不超过100。
对应每组测试数据,若其中一个大整数可以由另一个大整数重新排列得到,输出”Yes”,否则输出”No”。
按题意,需要统计两个大整数中 0 ~ 9 的出现次数是否相等。由于 0 可以排列在数字开头变为前导零,所以忽略 0 的出现次数。代码使用string类的 == 运算符快速解题。
int T;
string str1,str2;
int main()
{
for(read(T);T;--T)
{
cin>>str1>>str2;
sort(str1.begin(),str1.end());
sort(str2.begin(),str2.end());
while(str1[0]=='0') str1.erase(0,1);
while(str2[0]=='0') str2.erase(0,1);
printf(str1==str2?"Yes\n":"No\n");
}
return 0;
}
F 开灯问题
有n盏灯, 编号为1~n. 第1个人把所有灯打开, 第2个人按下所有编号为2的倍数的开关(这些灯将被关掉), 第3个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开, 开着的灯将被关闭), 依此类推. 一共有k个人, 问最后有哪些灯开着?
有多组测试数据. 输入的第一行是整数T(0<T≤100), 表示测试数据的组数. 每一组测试数据只有一行, 依次为正整数n和k, 两数之间有一个空格. k<=n<=1000.
对应每组输入, 输出一行还开着灯的编号, 按从小到大的顺序, 每个编号后有一个空格.
数字不大,就不写优化了。按题意,根据每个灯泡编号(假设为 d ),统计 1 ~ d 中出现过的 d 的因数个数即可。
int T,n,k;
int main()
{
for(read(T);T;--T)
{
read(n); read(k);
for (register int i=1;i<=n;++i)
{
bool stat=0;
for (register int v=1;v<=k&&v<=i;++v)
if(i%v==0) stat^=1;
if(stat) printf("%d ",i);
}
putchar('\n');
}
return 0;
}
G 蛇形填数
在n*n方阵里填入1,2,3,…,n*n, 要求填成蛇形. 例如 n=4 时方阵为:10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4有多组测试数据. 输入的第一行是整数T(1<=T<=20), 表示随后测试数据的组数. 每组测试数据占一行, 由正整数n组成. N<=20.
对应每组测试数据, 输出对应的蛇形矩阵, 每个数占四位, 右对齐.
蓝书原题,上一份蓝书上的std
int amaxn;
int main()
{
int n, x, y, tot = 0;
scanf("%d", &n);
memset(a, 0, sizeof(a));
tot = ax = 0 = 1;
while(tot < n * n)
{
while(x + 1 < n && !ax + 1) a++x = ++tot;
while(y - 1 >= 0 && !ax) ax = ++tot;
while(x - 1 >= 0 && !ax - 1) a--x = ++tot;
while(y + 1 < n && !ax) ax = ++tot;
}
for(x = 0; x < n; x++)
{
for(y = 0; y < n; y++) printf("%3d", ax);
printf("\n");
}
return 0;
}
我自己写的这道题的代码暴躁了点,用的是搜索,而且较为复杂。
int T,n,mat21;
bool vis21;
void sol(int val,int x,int y,int dir)
{
matx=val;
visx=true;
if(!visx+1&&x<n&&((dir==4&&(visx||y==n))||dir==1)) sol(val+1,x+1,y,1);
else if (!visx&&y>1&&(dir==1||dir==2)) sol(val+1,x,y-1,2);
else if (!visx-1&&x>1&&(dir==2||dir==3)) sol(val+1,x-1,y,3);
else if (!visx&&y<n&&(dir==3||dir==4)) sol(val+1,x,y+1,4);
}
int main()
{
for(read(T);T;--T)
{
read(n);
memset(vis,0,sizeof vis);
sol(1,1,n,1);
for (register int i=1;i<=n;++i)
{
for (register int v=1;v<=n;++v) printf("%d ",mati);
putchar('\n');
}
}
return 0;
}
H 数据大搜索
一行字符串可能含有多个正整数, 请找出这些整数, 并输出它们的和.
有多组测试数据. 输入的第一行是整数T(1<=T<=100), 表示随后测试数据的组数. 每组测试数据占一行, 由一个可能含有空格的字符串构成, 该字符串可能含有多个数字子串, 每个数字子串的数字个数不超过16, 数字子串的个数不超过10, 字符串的长度不超过1000.
对应每组测试数据, 输出该字符串所包含整数的和. 如果该字符串没有包含数字, 请输出0.
根据题意直接魔改了我常用的 read()
函数塞进去,可能不太好看
template<class _T>inline void read(_T &_a)
{
bool f=0; char _c=getchar(); _a=0;
while(_c<'0'||_c>'9'){ if(_c=='-') f=1; _c=getchar(); }
while(_c>='0'&&_c<='9'){ _a=(_a<<3)+(_a<<1)-'0'+_c; _c=getchar(); }
if(f) _a=-_a;
}
int T;
long long ans;
int main()
{
for(read(T);T;--T)
{
ans=0;
bool flag=true;
while(flag)
{
long long _a=0; char _c=getchar();
if(_c=='\n'||_c==EOF) break;
while(_c<'0'||_c>'9') { _c=getchar(); if(_c=='\n'||_c==EOF) { flag=false; break; } }
while(_c>='0'&&_c<='9'&&flag){ _a=(_a<<3)+(_a<<1)-'0'+_c; _c=getchar(); if(_c=='n'||_c==EOF) flag=false; }
ans+=_a;
}
printf("%lld\n",ans);
}
return 0;
}
I 旋转字符矩阵
读入一个n*n的字符矩阵, 绕矩阵中心顺时针旋转90度并输出结果.
有多组测试数据。第一行是整数T (T <= 100),表示测试数据的组数,随后有T组测试数据。每一组测试数据的第一行是正号数n, 随后是一个n*n的全由小写英文字符构成的字符矩阵, n < 100.
对应每组输入,输出绕矩阵中心顺时针旋转的字符矩阵, 每组给出完成后, 再输出一个空行.
按题意模拟即可
int T,n;
char t101;
int main()
{
for(read(T);T;--T)
{
read(n);
for (register int i=1;i<=n;++i)
{
for (register int v=1;v<=n;++v) ti=getchar();
getchar();
}
for (register int i=1;i<=n;++i)
{
for (register int v=n;v;--v) putchar(tv);
putchar('\n');
}
putchar('\n');
}
return 0;
}
J 猴子选大王
在m只猴子聚在一起选大王, 商定规则如下: 大家围成一圈, 按顺时针从1编号, 第一次从编号为1的开始报数, 以后循环进行, 当报到n时退出圈子, 下一只则重新从1开始报数, 圈子中剩下的最后一只猴子则为大王.
有多组测试数据. 输入的第一行是整数T(1<=T<=100), 表示随后测试数据的组数. 每组测试数据占一行, 由正整数m和n组成, 两数之间有一个空格. 2 <= m,n <= 200.
对应每组测试数据, 输出选出的大王的猴子编号.
写了个比较丑的链表
int T,n,m,nxt[201],now;
bool out[201];
int find(int id)
{
return out[nxt[id]]?nxt[id]=find(nxt[id]):nxt[id];
}
int main()
{
for(read(T);T;--T)
{
read(m); read(n);
memset(out,0,sizeof out);
for (register int i=1;i<m;++i) nxt[i]=i+1;
nxt[m]=1;
now=1;
for(register int i=1;i<m;++i)
{
for (register int i=1;i<n;++i) now=find(now);
out[now]=true;
now=find(now);
}
printf("%d\n",now);
}
return 0;
}
K 颠倒句子中的单词
读入一行英文句子,颠倒该句子的英文单词, 然后输出颠倒次序后的整个句子.
有多组测试数据.输入的第一行是整数T(1<=T<=20),表示随后测试数据的组数.每组测试数据是一行长度超过2, 但不超过1000的英文句子, 注意第一个单词前没有空格, 单词间的分隔符为一个空格, 结束也没有标点符号, 每个单词的长度不超过20.
对应每组测试数据, 输出一行颠倒次序的英文句子.
这题可以用 strtok()
很方便地做出来,可惜我做这题的时候还没能用上这个函数,于是手写了模拟。
int T,len;
char c[1005];
int main()
{
for(read(T);T;--T)
{
len=0;
do { c[++len]=getchar(); } while(c[len]!='\n'&&c[len]!=EOF);
c[len--]='\0';
for (register int i=len;i;--i)
if(c[i]==' ') c[i]='\0',printf("%s ",c+i+1);
printf("%s\n",c+1);
}
return 0;
}
L 今天是第几天
任给三个用一个空格隔开的整数,依次表示年、月、日,说出它是今年的第几天。定义该年的第1天是1月1日。
有多组测试数据.输入的第一行是整数T(1<=T<=200), 表示随后测试数据的组数. 每组测试数据占一行, 由三个分别表示年、月、日的正整数构成. 相邻两个数之间有一个空格.
对应每组测试数据, 输出一行的结果.
提示 一个年份 d 是闰年
可以用三元运算符这样表示:d 能被 100 整除 ? d 能被 400 整除 : d 能被 4 整除
int T,yea,mon,day,cal[13]={0,31,28,31,30,31,30,31,31,30,31,30,31},sum[13];
inline bool check() { return yea%100==0?yea%400==0:yea%4==0; }
int main()
{
for (register int i=1;i<=12;++i) sum[i]=sum[i-1]+cal[i];
for(read(T);T;--T)
{
read(yea);
read(mon);
read(day);
if(mon>2&&check()) printf("%d\n",sum[mon-1]+day+1);
else printf("%d\n",sum[mon-1]+day);
}
return 0;
}
后面的题实在太水,懒得写了,以后挑有意思的题写吧。。