PTA题目大赏
统计素数并求和
输入格式:
输入在一行中给出两个正整数M和N(1≤M≤N≤500)。
输出格式:
在一行中顺序输出M和N区间内素数的个数以及它们的和,数字间以空格分隔。
输入样例:
10 31
输出样例:
1 143
#include <stdio.h>
int main(){
int n,m,num,flag=0,add=0;
int M,N;
int a[501];
for(num=2;num<=500;num++){
a[num]=0;
} //定义并初始化数组,否则有可能出现a[i]!=0
a[1]=1; //标记非素数和和数的 1 为 1
scanf("%d %d",&M,&N);
for(n=2;n<=N;n++){
for(m=n*n;m<=N;m+=n){
a[m]=1;
}
} //遍历 2~N 的所有和数,并标记为 1
//printf("\n\n\n");
for(M;M<=N;M++){
if(a[M]==0){
//printf("%d\t",M);
flag++;
add+=M;
}
}
printf("%d %d",flag,add);
return 0;
}
求幂级数展开的部分和
题目:
已知: 已知函数 ex可以展开为幂级数1+x+x2/2!+x3/3!+⋯+xk/k!+⋯。现给定一个实数x,要求利用此幂级数部分和求ex的近似值,求和一直继续到最后一项的绝对值小于0.00001。
输入格式:
输入在一行中给出一个实数 x ∈ [0,5]。
输出格式:
在一行中输出满足条件的幂级数部分和,保留小数点后四位。
输入样例:
1.2
输出样例:
3.3201
#include <stdio.h>
#include <math.h>
int main (){
double x,num=1.0,add=1.0;
double i;
scanf("%lf",&x);
for(i=1;;i++){
num=(x*num)/i;
//每一轮都相当于(x/1)*(x/2)*(x/3)...(x/i)
//即就是 (x^i)/(i!)
add+=num;
if(num<0.00001)
break;
}
printf("%.4f",add);
return 0;
}
求分数序列前N项和
题目:
计算序列 2/1+32+5/3+8/5+… 的前N项之和。注意该序列从第2项起,每一项的分子是前一项分子与分母的和,分母是前一项的分子。
输入格式:
输入在一行中给出一个正整数N。
输出格式:
在一行中输出部分和的值,精确到小数点后两位。题目保证计算结果不超过双精度范围。
输入样例:
20
输出样例:
32.66
#include <stdio.h>
int main (){
double x=2,y=1,m,n;
//x,y为前一项分子与分母
//m,n为后一项分子与分母
//则 m=x+y n=x
int N,flag;
double add=2.0;
scanf("%d",&N);
for(flag=1;flag<N;flag++){
m=x+y; //3=1+2
n=x; //2=2
add+=(m/n);//3/2
x=m; //x=3
y=n; //y=2
}
printf("%.2lf",add);
return 0;
}
特殊a串数列求和
题目:
给定两个均不超过9的正整数a和n,要求编写程序求a+aa+aaa++⋯+aa⋯a(n个a)之和。
输入格式:
输入在一行中给出不超过9的正整数a和n
输出格式:
在一行中按照“s = 对应的和”的格式输出。
输入样例:
2 3
输出样例:
s = 246
#include <stdio.h>
#include <math.h>
int main(){
//注意题目不是指从 a^1~a^n 求和
//而是像 1+11+111+....求和
int a,n,add=0,flag;
scanf("%d %d",&a,&n);
int sum=0;
for(flag=0;flag<n;flag++){
sum=sum*10+a;
add+=sum;
}
printf("s = %d",add);
return 0;
}
水仙花数
题目:
水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身。例如:153=13+53+33。 本题要求编写程序,计算所有N位水仙花数。
输入格式:
输入在一行中给出一个正整数N(3≤N≤7).
输出格式:
按照递增顺序输出所有N位水仙花数,每个数字占一行.
输入样例:
3
输出样例:
153
370
371
407
#include <stdio.h>
int pow(int x,int y);
int main (){
int N;
int min,max;
int flag1,flag2;
int num,add=0;
scanf("%d",&N);
min=pow(10,N-1);
max=pow(10,N);
for(flag1=min;flag1<max;flag1++){
num=flag1;
for(flag2=1;flag2<=N;flag2++){
add+=pow((num%10),N);
num=num/10;
}
if(add==flag1){
printf("%d\n",flag1);
}
add=0;
}
return 0;
}
int pow(int x,int y){
int flag;
int a=1;
for(flag=1;flag<=y;flag++){
a*=x;
}
return a;
}
//若调用<math.h>函数库,则当N=7时,会出现运行超时的情况,因为pow()函数是浮点运算,
//且需调用<math.h>函数库
* 电文环形解密
题目:
将26个英文字母按顺时针方向排成一个圆环。密钥是一个整数。
加密方法:
若密钥 key ≥ 0 ,则从明文字母开始顺时针方向走 |key|步得到秘文字母;
若密钥 key < 0 ,则从明文字母开始逆时针方向走 |key|步得到密文字母;
输入格式:
密钥(任意整数)
密文电文(以回车结束)
输出格式:
明文电文(以回车结束)
输入样例:
2
K nqxg aqw!
输出样例:
I love you!
#include <stdio.h>
int main (){
int key;
char miwen;
scanf("%d",&key);
key%=26;
//确保密钥在26以内
getchar();
do{//先读入一字符,然后再判断其是否为字母,所以用 do-while 语句
scanf("%c",&miwen);
if((miwen>='a') && (miwen<='z')){
key <0 ?
miwen='a'+((miwen-'a'-key)%26)
:
(miwen='z'-(('z'-miwen+key)%26));
printf("%c",miwen);
//使用 A ? B : C 语句
//如果 key<0, 明文转密文为逆时针,则密文转明文为顺时针
//则计算 '当前字母' - 'a' 的距离,再加上key的距离,即可得到明文字母距离a的距离
//如果 key>0, 明文转密文为顺时针,则密文转明文为逆时针
//则计算 'z' - '当前字母' 的距离,再加上key的距离,即可得到明文字母距离z的距离
//为什么顺时针用 'a'+距离;而逆时针用 'z'-距离?
//原因:顺时针从'a'开始确保不会溢出26,逆时针同理
}else if((miwen>='A') && (miwen<='Z')){
key <0 ?
miwen='A'+((miwen-'A'-key)%26)
:
(miwen='Z'-(('Z'-miwen+key)%26));
printf("%c",miwen);
}else{
printf("%c",miwen);
}
}while(miwen !='\n');
return 0;
}
星期几?
给定一个1900 ~ 2100 范围内日期,输出这个日期是星期几.
(1900/01/01为星期一)
输入格式:
输入数据的格式为YYYY/MM/DD组成,具体参见sample intput.
输出格式:
对于每组输入数据,输出一行,表示该日期是星期几英文单词.
输入样例:
2011/11/17
输出样例:
thursday
#include <stdio.h>
int main(){
int a;
int b;
int c;
int i;
int day[13];
int sum,add=0,flag;
//算出现在是今年第几天
day[1]=31;
day[2]=28;
day[3]=31;
day[4]=30;
day[5]=31;
day[6]=30;
day[7]=31;
day[8]=31;
day[9]=30;
day[10]=31;
day[11]=30;
day[12]=31;
scanf("%d/%d/%d",&a,&b,&c);
sum=0;
for(i=1;i<=b-1;i++)
sum+=day[i];
sum+=c;
//先不考虑闰年今天是当年第几天
if((a%400==0 || (a%4==0 && a%100!=0)) && b>=3)
sum++;
//判断是否闰年,且月份大于 2,若是则在总天数+1
for(flag=1900;flag<a;flag++){
add+=365;
if((flag%400==0) || (flag%4==0 && flag%100!=0)){
add++;
}
//遍历1900~到当前年份每一年, 先+365,如若为闰年++
}
add+=sum;
//计算出总天数,对7取余,即可得到星期几
switch(add%7){
case 1:
printf("monday");
break;
case 2:
printf("Tuesday");
break;
case 3:
printf("Wednesday");
break;
case 4:
printf("thursday");
break;
case 5:
printf("friday");
break;
case 6:
printf("saturday");
break;
case 0:
printf("sunday");
break;
}
return 0;
}
* 找出不是两个数组共有的元素
给定两个整数数组,本题要求找出不是两者共有的元素.
输入格式:
输入分别在两行中给出两个整型数组,每日行先给出正整数N(≤20),随后是N个整数,其间以空格分隔.
输出格式:
在一行中按照数字给出的顺序输出不是两个数组共有的元素,数字间以空格分隔,但行末不得有多余空格.题目保证至少存在一个这样的数字,同一数字不重复输出.
输入样例:
10 3 -5 2 8 0 3 5 -15 9 100
11 6 4 8 2 6 -5 9 0 100 8 1
输出样例:
3 5 -15 6 4 1
#include<stdio.h>
int main()
{
int a[20], b[20], c[20];
int m, n, i, j, k=0;
scanf("%d", &m);
for(i=0; i<m; i++){
scanf("%d", &a[i]);
}
scanf("%d", &n);
for(i=0; i<n; i++)
scanf("%d", &b[i]);
for(i=0; i<m; i++){
for(j=0; j<n; j++){
if(a[i]==b[j])
break;
}
if(j>=n){
c[k]=a[i];
k++;
}
}
for(i=0; i<n; i++){
for(j=0; j<m; j++){
if(b[i]==a[j])
break;
}
if(j>=m){
c[k]=b[i];
k++;
}
}
printf("%d", c[0]);
for(i=1; i<k; i++){
for(j=0; j<i; j++){
if(c[i]==c[j])
break;
}
if(j>=i)
printf(" %d", c[i]);
}
return 0;
}
组个最小数
给定数字0-9各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能(注意0不能做首位)。例如:给定两个0,两个1,三个5,一个8,我们得到的最小的数就是10015558。现给定数字,请编写程序输出能够组成的最小的数。
输入格式:
输入在一行中给出10 个非负数,顺序表示我们拥有数字0、数字1、……数字9的个数。整数间用一个空格分隔。10个数字的总个数不超过50,且至少拥有1个非0的数字。
输出格式:
在一行中输出能够组成的最小的数
输入样例:
2 2 0 0 0 3 0 0 1 0
输出样例:
10015558
#include <stdio.h>
int main (){
int a[11];
int i,t;
for(i=0;i<10;i++){
scanf("%d",&a[i]);
}
for(i=1;i<10;i++){
if(a[i]!=0){
printf("%d",i);
a[i]--;
break;
}
}//输出第一个非0数,并将其总数减1
for(i=0;i<10;i++){
for(t=a[i];t>0;t--){
printf("%d",i);
}
}//从数组0开始,依次按个数输出
return 0;
}
矩阵运算
给定一个n×n的方阵,本题要求计算该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。副对角线为从矩阵的右上角至左下角的连线
输入格式:
输入第一行给出正整数n(1<n≤10);随后n行,每行给出n个整数,其间以空格分隔。
输出格式:
在一行中给出该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。
输入样例:
4
2 3 4 1
5 6 1 1
7 1 8 1
1 1 1 1
输出样例:
35
#include <stdio.h>
int main(){
int n,i,j,add=0;
scanf("%d",&n);
int a[n][n];
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&a[i][j]);
}
}
for(i=0;i<n;i++){
a[n-1][i]=0;
}//最后一行线归0
for(i=0;i<n;i++){
a[i][n-1]=0;
}//最后一列归0
for(i=0;i<n;i++){
j=n-1-i;
a[i][j]=0;
}//副对角线归0
for(i=0;i<n;i++){
for(j=0;j<n;j++){
add+=a[i][j];
}
}//从[0][0]到[n-1][n-1]求和
printf("%d",add);
return 0;
}
找鞍点
一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。本题要求编写程序,求一个给定的n阶方阵的鞍点。
输入格式:
输入第一行给出一个正整数n(1≤n≤6)。随后n行,每行给出n个整数,其间以空格分隔。
输出格式:
输出在一行中按照“行下标 列下标”(下标从0开始)的格式输出鞍点的位置。如果鞍点不存在,则输出“NONE”。题目保证给出的矩阵至多存在一个鞍点。
输入样例:
4
1 7 4 1
4 8 3 6
1 6 1 2
0 7 8 9
输出样例:
2 1
输入样例:
2
1 7
4 1
输出样例:
NONE
//MINE
//鞍点:行上最大、列上最小
#include <stdio.h>
int main(){
int n,num=0;
int i,j,k,T=0;
int max;
scanf("%d",&n);
int a[n][n];
n-=1;
for(i=0;i<=n;i++){
for(j=0;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
for(i=0;i<=n;i++){
max=a[i][0];
num=0;
for(j=0;j<n;j++){
if(max<=a[i][j+1]){
max=a[i][j+1];
num=j+1;
}
}
//此时已经找到第 i 行最大值
for(k=0;k<=n;k++){
if(a[k][num]<max){
T=1;
continue;
}
}
if(T==0){
printf("%d %d",i,num);
T=1;
break;
}
T=0;
}
if(T==0){
printf("NONE");
}
return 0;
}
* 整数拆分
给定一个整数n,将其无序拆分成最大数为k的拆分数,(n,k不超出100) 要求:所有的拆分方案不重复。 如当n=4,k=4时,一共有5种拆分方案,拆分如下
(1)4=1+1+1+1 (2)4=1+1+2 (3)4=1+3 (4)4=2+2 (5)4=4
输入格式:
每一行输入一组整数n,k,遇到键盘结束符^Z或文件结束符EOF时结束输入。
输出格式:
按行输出每组的拆分方案数.
输入样例:
4,4
5,4
输出样例;
5
6
#include<stdio.h>
int main() {
int n, k;
while (scanf("%d, %d", &n, &k) != EOF) {
int dp[101][101];
int i, j;
for (i = 1; i <= n; i++) {
for (j = 1; j <= k; j++) {
if (j == 1 || i == 1)
dp[i][j] = 1;
else if (j == i) {
dp[i][j] = dp[i][j - 1] + 1;
}
else if (i < j) {
dp[i][j] = dp[i][i];
}
else if (i > j) {
dp[i][j] = dp[i][j - 1] + dp[i - j][j];
}
}
}
printf("%d\n", dp[n][k]);
}
return 0;
}
//这道题不会,纯傻*题目
* 完美的代价
回文串是一种特殊的字符串,它从左往右读和从右往左读是一样的,有人认为回文串是一种完美的字符串。现在给你一个字符串,它不一定是回文的,请你计算最少的交换次数使得该字符串变成一个回文串。这里的交换指将字符串中两个相邻的字符互换位置。 例如所给的字符串为”mamad”,第一次交换a和d,得到”mamda”,第二次交换m和d,得到”madma”;第三次交换最后面的m和a,得到”madam”。
输入格式:
第一行是一个整数N(N<=80),表示所给的字符串长度,第二行是所给的字符串,长度为N且只包含小写英文字母.
输出格式:
如果所给的字符串能经过若干次交换变成会问串,则输出所需的最少交换次数;否则,输出Impossible.
输入样例:
5
mamad
输出样例:
3
/*
完美的代价:通过交换相邻字符,使原字符串化为回文字符串 。
*/
#include<stdio.h>
#include<stdlib.h>
int main(){
int i,j,l,n,k,sum=0,flat=1,c=-1;
char *a;
scanf("%d",&n);
a=(char *)malloc(n*sizeof(char));
scanf("%s",a);
j=n-1;
//利用贪心的思想,将每个遍历的字符找到后面与他相同的然后交换到正确的位置时所需的交换次数
for(i=0;i<j;i++){
for(k=j;k>=i;k--){
if(k==i){//说明没有找到与a[i]相同的字符
if(n%2==0||c!=-1){//如果n为偶数或者a[i]不是唯一一个单个无相同字符
flat=0;
break;
}
c=1;//n为奇数,将第一个单个的字符a[i]移到中间位置所需的交换次数
sum=sum+n/2-i;
break;
}
if(a[k]==a[i]){
for(l=k;l<j;l++){
a[l]=a[l+1];
}
a[j]=a[i];
sum=sum+j-k;
j--;
break;
}
}
if(flat==0){
break;
}
}
if(flat==0)
printf("Impossible");
else if(sum==0)
printf("0");
else
printf("%d\n",sum);
return 0;
}
数组元素的删除
完成数组元素的移动功能:假设数组有n个元素,输入一个数x,把数组的第x个位置的元素删除了,后面的元素依次前进一个位置。 重复若干次这样的删除,得到最后的结果。
输入格式:
第一行包括一个整数n(1<=n<=100),表示数组元素的个数。 第二行输入n个数组元素,均为整数,用空格隔开。 第三行输入一个数k(1<=k<=100),表示要进行k次删除。 接下来k行,每行一个数x,表示要删除第x个元素。
输出格式:
输出经过k次删除后的数组,每两个元素之间用空格隔开
输入样例:
10 1 2 3 4 5 6 7 8 9 10 4 3 2 4 6
输出样例:
1 4 5 7 8 10
#include <stdio.h>
int main(){
int i,n,k,x;
scanf("%d",&n);
int a[n];
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
scanf("%d",&k);
while(k--){
scanf("%d",&x);
for(i=x;i<n;i++){
a[i]=a[i+1];
}
n--;
}
for(i=1;i<=n;i++){
printf("%d",a[i]);
if(i!=n)
printf(" ");
}
return 0;
}
* 九宫格输入法
假设有九宫格输入法键盘布局如下:
[ 1,.?! ] [ 2ABC ] [ 3DEF ] [ 4GHI ] [ 5JKL ] [ 6MNO ] [ 7PQRS ] [ 8TUV ] [ 9WXYZ] [ 0空 ]
注意:中括号
[ ]
仅为了表示键盘的分隔,不是输入字符。每个中括号中,位于首位的数字字符即是键盘的按键,按一下即可输入该数字字符。多次按同一个键,则输入的字符依次循环轮流,例如按两次3
,则输入D
;按5次7
,则输入S
;按6次2
,则输入A
。按键0
的输入组合是0
和空格
字符,即按两次0
输入空格。你需要对于给定的按键组合,给出该组合对应的文本。
输入格式:
输入在一行中给出数个字符的按键组合(例如999
表示按3次9
),每个字符的按键组合之间用空格间隔,最后一个输入法组合之后以换行结束。输入数据至少包括一个字符的按键组合,且输入总长度不超过500个字符。
输出格式:
在一行中输出该案件组合对应的文本.
输入样例:
22 5555 22 666 00 88 888 7777 4444 666 44
输出样例:
ALAN TURING
#include<stdio.h>
char result(int a,char s){
int array[10][5]=
{
{49,44,46,63,33},//1
{50,65,66,67},//2
{51,68,69,70},//3
{52,71,72,73},//4
{53,74,75,76},//5
{54,77,78,79},//6
{55,80,81,82,83},//7
{56,84,85,86},//8
{57,87,88,89,90},//9
{48,32}//0
};
if(s=='1'||s=='7'||s=='9'){
while(a>5) a-=5;
printf("%c",array[s-'0'-1][a-1]);
}else if(s=='0'){
while(a>2) a-=2;
printf("%c",array[9][a-1]);
}else{
while(a>4) a-=4;
printf("%c",array[s-'0'-1][a-1]);
}
}
int main(void){
char c[500];
int i;
//输入字符串
for(i=0;;i++){
scanf("%c",&c[i]);
if(c[i]=='\n') break;
}
//计算并输出
for(i=0;c[i]!='\n';i++){
int show=1;
for(;c[i]==c[i+1];i++){
show++;
}
result(show,c[i]);
if(c[i+1]==' ') i++;
}
}
* 敲笨钟
微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。为了增加敲钟的趣味性,还会糟改几句古诗词。其糟改的方法为:去网上搜寻压“ong”韵的古诗词,把句尾的三个字换成“敲笨钟”。例如唐代诗人李贺有名句曰:“寻章摘句老雕虫,晓月当帘挂玉弓”,其中“虫”(chong)和“弓”(gong)都压了“ong”韵。于是这句诗就被糟改为“寻章摘句老雕虫,晓月当帘敲笨钟”。
现在给你一大堆古诗词句,要求你写个程序自动将压“ong”韵的句子糟改成“敲笨钟”。
输入格式:
输入首先在第一行给出一个不超过 20 的正整数 N。随后 N 行,每行用汉语拼音给出一句古诗词,分上下两半句,用逗号,
分隔,句号.
结尾。相邻两字的拼音之间用一个空格分隔。题目保证每个字的拼音不超过 6 个字符,每行字符的总长度不超过 100,并且下半句诗至少有 3 个字。
输出格式:
对每一行诗句,判断其是否压“ong”韵。即上下两句末尾的字都是“ong”结尾。如果是压此韵的,就按题面方法糟改之后输出,输出格式同输入;否则输出Skipped
,即跳过此句。
输入样例:
5 xun zhang zhai ju lao diao chong, xiao yue dang lian gua yu gong. tian sheng wo cai bi you yong, qian jin san jin huan fu lai. xue zhui rou zhi leng wei rong, an xiao chen jing shu wei long. zuo ye xing chen zuo ye feng, hua lou xi pan gui tang dong. ren xian gui hua luo, ye jing chun shan kong.
输出样例:
xun zhang zhai ju lao diao chong, xiao yue dang lian qiao ben zhong. Skipped xue zhui rou zhi leng wei rong, an xiao chen jing qiao ben zhong. Skipped Skipped
#include<stdio.h>
#include<string.h>
int judge(char a[][101],int row)
{
int j=0;
char temp[]={"ong,"};
char t[]={"ong."};
if(strstr(a[row],temp)!=NULL)
{
if(strstr(a[row],t)!=NULL)
return 1;
}
return 0;
}
void display(char a[][101],int row)
{
int j=0;
int count=strlen(a[row]);
int blank=0;
char insert[]={"qiao ben zhong."};
for(j=count-1;;--j)
{
if(a[row][j]==32)
++blank;
if(a[row][j]==',') //解决下半句诗只有三个字问题
++blank;
if(blank==3)
{
j=j+1;
break;
}
}
strcpy(a[row]+j,insert);
return;
}
int main(void)
{
char input[21][101]={0};
int n=0;
int i=0;
scanf("%d",&n);
getchar(); //**此处是重点!!!**
for(i=0;i<n;++i)
gets(input[i]);
for(i=0;i<n;++i)
{
if(judge(input,i))
{
display(input,i);
printf("%s\n",input[i]);
}
else
printf("Skipped\n");
}
return 0;
}
* 删除重复字符
本题要求编写程序,将给定字符串去掉重复的字符后,按照字符ASCII码顺序从小到大排序后输出。
输入格式:
输入是一个以回车结束的非空字符串(少于80个字符)
输出格式:
输出去重排序后的结果字符串
输入样例:
ad2f3adjfeainzzzv
输出样例:
23adefijnvz
#include <stdio.h>
int main(){
char a[90],k;
int i,j,longs=0;
gets(a);
for(i=0;i<=80 && a[i]!='\0';i++){
longs++;
}
for(i=0;i<longs-1;i++){
for(j=i+1;j<longs;j++){
if(a[i]>a[j]){
k=a[i];
a[i]=a[j];
a[j]=k;
}
}
}
for(i=0;i<longs-1;i++){
while(a[i]==a[i+1]){
for(j=i+1;j<longs-1;j++){
a[j]=a[j+1];
}
a[longs-1]='\0';
longs--;
}
}
for( i=0;i<longs;i++)
putchar(a[i]);
return 0;
}