http://codeup.cn/contest.php?cid=100000566php
#include <stdio.h> int main() { printf("%s", "This is my first c program!"); return 0; }
#include <stdio.h> int main() { char *asterisk = "********************"; char *s = "Very Good!"; printf("%s\n%s\n%s", asterisk, s, asterisk); return 0; }
int main() { /* 设置3个变量a, b, sum,其中a, b用来存放两个整数,sum用来存放a, b两个数的和, 经过赋值(即采用赋值运算符"=")的方式将a初始化为123,b初始化为456,并把两个 变量相加的结果赋值给sum。*/ int a, b, sum; a = 123, b = 456; sum = a + b; printf("sum=%d", sum); return 0; }
#include <stdio.h> int main() { int a, b; scanf("%d%d", &a, &b); printf("%d", a+b); return 0; }
#include <stdio.h> #include <math.h> int main() { /* 求一元二次方程ax2+bx+c=0的根,三个系数a, b, c由键盘输入,且a不能为0,且保证b2-4ac>0。 程序中所涉及的变量均为double类型。 输入 以空格分隔的一元二次方程的三个系数,双精度double类型 输出 分行输出两个根以下(注意末尾的换行): r1=第一个根 r2=第二个根 结果输出时,宽度占7位,其中小数部分2位。*/ double a, b, c; scanf("%lf%lf%lf", &a, &b, &c); double r1, r2; // 求根公式 x=[-b±√(b2-4ac)]/2a r1 = (double)((-b + sqrt(pow(b, 2.0) - 4*a*c)) / (2 * a)); r2 = (double)((-b - sqrt(pow(b, 2.0) - 4*a*c)) / (2 * a)); printf("r1=%7.2f\nr2=%7.2f", r1, r2); }
#include <stdio.h> int main() { /* 从键盘输入三个字符BOY,而后把他们输出到屏幕上 输入 BOY三个字符,中间无分隔符 输出 BOY,注意末尾的换行 */ char s[10]; scanf("%s", s); printf("%s", s); return 0; }
http://codeup.cn/contest.php?cid=100000567java
#include <stdio.h> #include <math.h> int main() { /* 不保证b2-4ac>0, 若是方程无实根,输出一行以下信息(注意末尾的换行) No real roots! */ double a, b, c, cond, r1, r2; scanf("%lf%lf%lf", &a, &b, &c); cond = pow(b, 2.0) - 4*a*c; if (cond >= 0) { r1 = (double)(-b + sqrt(cond)); r2 = (double)(-b - sqrt(cond)); printf("r1=%7.2f\nr2=%7.2f", r1, r2); } else { printf("No real roots!\n") } return 0; }
#include <stdio.h> int main() { /* 输入 用空格分隔的两个实数。 输出 从小到大输出这两个实数,中间以空格来分隔, 小数在前,大数在后。小数点后保留2位小数。末尾输出换行符。 */ double a, b; scanf("%lf%lf", &a, &b); if (a > b) { printf("%.2f %.2f", b, a); } else { printf("%.2f %.2f", a, b); } return 0; }
#include <stdio.h> void swap(double *a, double *b) { double temp; temp = *a; *a = *b; *b = temp; } int main() { /* 输入 输入以空格分隔的三个实数 输出 按照从小到大的顺序输出这三个实数,中间以空格分隔,最小值在前, 最大值在后。小数点后保留2位小数。末尾输出换行。 */ double a, b, c; scanf("%lf%lf%lf", &a, &b, &c); if (a > b) swap(&a, &b); if (b > c) swap(&b, &c); if (a > b) swap(&a, &b); printf("%.2f %.2f %.2f\n", a, b, c); return 0; }
#include <stdio.h> int main() { /* 输入 以空格分割的三个整数。 输出 三个数中的最大值,末尾换行。*/ int a, b, c; scanf("%d%d%d", &a, &b, &c); if (a >= b && a >= c) printf("%d\n", a); else if (b >= a && b >= c) printf("%d\n", b); else if (c >= a && c >= b) printf("%d\n", c); return 0; }
#include <stdio.h> int main() { double income, bonus; scanf("%lf", &income); /* 某企业发放的奖金根据利润提成。利润I低于或等于100000时,奖金可提10%; 利润(100000<I<=200000)时,低于100000元的部分仍按10%提成,高于100000元的部分提成比例为7.5%; 200000<I<=400000时,低于200000元的部分仍按上述方法提成(下同),高于200000元的部分按5%提成; 400000<I<=600000元时,高于400000元的部分按3%提成; 600000<I<=1000000时,高于600000元的部分按1.5%提成; I>1000000元时,超过1000000元的部分按1%提成。 输入 企业利润,小数,双精度double类型 输出 应发奖金数,保留2位小数,末尾换行。*/ double b1, b2, b3, b4, b5; b1 = (double)(100000 * 10) / 100; b2 = b1 + (double)(100000 * 7.5) / 100; b3 = b2 + (double)(200000 * 5) / 100; b4 = b3 + (double)(200000 * 3) / 100; b5 = b4 + (double)(400000 * 1.5) / 100; if (income <= 100000) { bonus = (double)(income * 10) / 100; } else if (100000 < income && income <= 200000) { bonus = b1 + ((income - 100000) * 7.5) / 100; } else if (200000 < income && income <= 400000) { bonus = b2 + ((income - 200000) * 5.0) / 100; } else if (400000 < income && income <= 600000) { bonus = b3 + ((income - 400000) * 3.0) / 100; } else if (600000 < income && income <= 1000000) { bonus = b4 + ((income - 600000) * 1.5) / 100; } else { bonus = b5 + ((income - 1000000) * 1.0) / 100; } printf("%.2f\n", bonus); return 0; }
http://codeup.cn/contest.php?cid=100000567node
#include <stdio.h> int main() { int i=1, sum=0; while (i <= 100) { sum += i; i++; } printf("%d\n", sum); return 0; } /*---------------------------------------------------*/ #include <stdio.h> int main() { printf("%d\n", 100 * (100 + 1) / 2); return 0; }
#include <stdio.h> int main() { int i = 0, sum = 0; do { sum += i; i++; } while (i <= 100); printf("%d\n", sum); return 0; }
#include <cstdio> int main() { int sum = 0; for (int i = 0; i < 100; i++, sum+=i); printf("%d\n", sum); return 0; }
#include <cstdio> int main() { int n; scanf("%d", &n); printf("%d\n", n * (n + 1) / 2); return 0; }
#include <cstdio> int main() { /* 求1+2+3+...和的程序,要求获得使和数大于1000的最小正整数N。*/ int i, sum = 0; for (i = 1; sum <= 1000; i++, sum += i); printf("%d\n", i); return 0; }
#include <cstdio> int main() { for (int i=1; i <= 4; i++) { for (int j=1; j <= 5; j++) { printf("%3d", i*j); if (i * j % 5 == 0) printf("\n"); } } return 0; }
#include <cstdio> /* 用以下公式 pi/4 = 1-1/3+1/5-1/7....求圆周率PI的近似值,直到发现某一项的绝对值 小于10-6为止(该项不累加)。 若是须要计算绝对值,可使用C语言数学库提供的函数fabs,如求x的绝对值,则为fabs(x). 输出 PI=圆周率的近似值 输出的结果总宽度占10位,其中小数部分为8位。末尾输出换行。 */ int main() { double pi = 0.0; for (double term = 1, i = 1, j = 3; fabs(term) >= 1e-6; j+=2) { pi += term; i = -i; term = i / j; } printf("PI=%10.8f\n", pi * 4); return 0; }
#include <cstdio> /*输入 一个不超过50的正整数 输出 Fibonacci数列的第n个数,末尾输出换行。*/ int fibo(int n) { if (n == 1 || n == 2) return 1; else return fibo(n-1) + fibo(n-2); } int main() { int N; scanf("%d", &N); printf("%d\n", fibo(N)); return 0; }
#include <cstdio> /* 有一个分数序列:2/1 , 3/2 , 5/3 , 8/5 , 13/8 , 21/13 ... 求出这个数列的前20项之和. 输出 小数点后保留6位小数,末尾输出换行。*/ double top(int n) { if (n == 1) return 2; else if (n == 2) return 3; else return top(n-1) + top(n-2); } double bottom(int n) { if (n == 1) return 1; else if (n == 2) return 2; else return bottom(n-1) + bottom(n-2); } int main() { double sum = 0.0; for (int i = 1; i <= 20; i++) sum += (double)(top(i) / bottom(i)); printf("%.6f\n", sum); return 0; }
#include <cstdio> /* 第一行输入以空格分隔的9个整数数,要求按从小到大的顺序输入。 第二行输入一个整数, 将此整数插入到前有序的9个数中,使得最终的10个数 依然是从小到大有序的。 输出 从小到大输出这10个数,每一个数一行。*/ int main() { int a[10], temp; for (int i = 0; i < 9; i++) scanf("%d", &a[i]); scanf("%d", &temp); /* 相似插入排序 */ int i; for (i = 9; a[i-1] > temp && i >= 0; i--) a[i] = a[i-1]; a[i] = temp; for (int i=0; i < 10; i++) printf("%d\n", a[i]); return 0; }
#include <cstdio> /* 将一个长度为10的整型数组中的值按逆序从新存放。 输入 从键盘上输入以空格分隔的10个整数。 输出 按相反的顺序输出这10个数,每一个数占一行。*/ int main() { int a[10]; for (int i=0; i<10; i++) { scanf("%d", &a[i]); } for (int i=0; i<5; i++) { int temp = a[9-i]; a[9-i] = a[i]; a[i] = temp; } for (int i=0; i<10; i++) { printf("%d\n", a[i]); } return 0; }
#include <cstdio> #include <cstring> /* 输入 输入只包含一个正整数n,表示将要输出的杨辉三角的层数。 输出 对应于该输入,请输出1-相应层数的杨辉三角,每一层的整数之间用一个空格隔开, 最多输出10层 */ int main() { int n, a[10] = {1, 1}; scanf("%d", &n); for (int i = 1; i <= n; i++) { /* 打印第一、2层 */ if (i == 1) printf("%d\n", a[0]); else if (i == 2) printf("%d %d\n", a[0], a[1]); else { /* 打印其余层 */ int temp[10]; temp[0] = a[0]; int j; /* 从a的如今一层推导出下一层, 存入临时数组 */ for (j = 1; j <= i-2; j++) { temp[j] = a[j-1] + a[j]; } temp[j] = 1; /* 打印这一层 */ for (int k=0; k < j; k++) { printf("%d ", temp[k]); } printf("%d\n", temp[j]); /* 更新数组a */ for (int m=0; m < i; m++) { a[m] = temp[m]; } } } return 0; }
#include <cstdio> #include <cstring> /* 第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。 要求根据密码译回原文,并输出。 输入 输入一行密文; 输出 解密后的原文,单独占一行。*/ int main() { char s[100], t[100]; gets(s); for (int i=0; i < strlen(s); i++) { if (s[i] >= 65 && s[i] <= 90) { s[i] = 155 - s[i]; //'A'65 Z'90' } else if (s[i] >= 97 && s[i] <= 122) { s[i] = 219 - s[i]; // 'a'97 'z'122 } } puts(s); return 0; }
这个题目彷佛只是对等长字符串进行比较,若是不等长的话…须要修改一下。ios
#include <cstdio> #include <cstring> /* 比较两个字符串s1和s2的大小,若是s1>s2,则输出一个正数; 若s1=s2,则输出0;若s1<s2,则输出一个负数。 要求:不用strcpy函数;两个字符串用gets函数读入。 输入 输入2行字符串 输出 一个整数,表示这两个字符串 比较的差值,单独占一行。*/ int main() { char str1[100], str2[100]; gets(str1); gets(str2); int res, lt = strlen(str1) < strlen(str2) ? strlen(str1) : strlen(str2); for (int i = 0; i < lt; i++) { res = str1[i] - str2[i]; if (res) break; } printf("%d\n", res); return 0; }
#include <cstdio> /* 输入 10个整数,以空格分隔 输出 将输入的10个整数逆序输出,每一个数占一行。 */ int main() { int a[10]; for (int i = 0; i < 10; i++) scanf("%d", a + i); for (int i = 9; i >= 1; i--) printf("%d\n", a[i]); printf("%d", a[0]); return 0; }
这是最好的求解Fibonacci数列的方法。git
#include <cstdio> /* 输入 无 输出 Fibonacci数列的前20个数,每一个数占一行。 */ int main() { int fib[20] = {1, 1}; for (int i = 2; i < 20; i++) fib[i] = fib[i-1] + fib[i-2]; for (int i = 0; i < 20; i++) printf("%d\n", fib[i]); return 0; }
#include <cstdio> int main() { int a[10]; for (int i = 0; i < 10; i++) scanf("%d", a + i); /* 标记+冒泡排序 */ for (int i = 9; i >= 0; i--) { int flag = 1; for (int j = 0; j < i; j++) { if (a[j] > a[j+1]) { int temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; flag = 0; } } if (flag) break; } for (int i = 0; i < 9; i++) printf("%d\n", a[i]); printf("%d", a[9]); return 0; }
#include <cstdio> /* 输入 2行数据,每行3个整数,以空格分隔。 输出 行列互换后的矩阵,3行,每行2个数据,以空格分隔。*/ int main() { int a[2][3], aT[3][2]; for (int i = 0; i < 2; i++) for (int j = 0; j < 3; j++) scanf("%d", *(a + i) + j); /* 转置操做 */ for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { aT[j][i] = a[i][j]; } } for (int i = 0; i < 2; i++) printf("%d %d\n", aT[i][0], aT[i][1]); printf("%d %d", aT[2][0], aT[2][1]); return 0; }
#include <cstdio> #include <cstring> /* 输入 输入3行,每行均为一个字符串。 输出 一行,输入三个字符串中最大者。*/ int main() { char s1[100], s2[100], s3[100], *Max; gets(s1); gets(s2); gets(s3); Max = s1; if (strcmp(Max, s2) < 0) Max = s2; if (strcmp(Max, s3) < 0) Max = s3; printf("%s", Max); return 0; }
我这里使用的是原地修改, 懒得返回值了。web
#include <cstdio> #include <cstring> /* 输入 一行字符串。 输出 输入字符串反序存放后的字符串。单独占一行。*/ void strReverse(char s[]) { int len = strlen(s); for (int i = 0; i < len / 2; i++) { char temp = s[i]; s[i] = s[len-1-i]; s[len-1-i] = temp; } } int main() { char s[100]; gets(s); strReverse(s); printf("%s\n", s); return 0; }
/* 输入 一个字符串(一行字符)。 输出 该字符串全部元音字母构成的字符串。行尾换行。*/ void vowels(char s1[], char s2[]) { int len = strlen(s1), j = 0; for (int i = 0; i < len; i++) { if (s1[i] == 'a' || s1[i] == 'e' || s1[i] == 'i' || s1[i] == 'o' || s1[i] == 'u') { s2[j] = s1[i]; j++; } } s2[j] = '\0'; } int main() { char s1[100], s2[100]; gets(s1); vowels(s1, s2); printf("%s\n", s2); return 0; }
#include <cstdio> /* 输入 两个用空格隔开的整数a和b。 输出 按先大后小的顺序输出a和b,用空格隔开。请注意行尾输出换行。*/ int main() { int a, b; scanf("%d%d", &a, &b); if (a > b) printf("%d %d\n", a, b); else printf("%d %d\n", b, a); return 0; }
#include <cstdio> /*输入 三个用空格隔开的整数a、b和c。 输出 按先大后小的顺序输出a、b和c,用空格隔开。请注意行尾输出换行。*/ int main() { int a[3]; scanf("%d%d%d", &a[0], &a[1], &a[2]); for (int i=0; i < 2; i++) { for (int *p=a; p < a + 2; p++) { if (*p < *(p+1)) { int temp = *p; *p = *(p+1); *(p+1) = temp; } } } printf("%d %d %d\n", *a, *(a+1), *(a+2)); return 0; }
#include <cstdio> /* 给定字符串定义char *a = “I love China!”, 读入整数n,输出在进行了a = a + n这个赋值操做之后字符指针a对应的字符串。 输入 一个整数n,保证0<=n<13. 输出 输出进行了题目描述中赋值操做以后a对应的字符串. 请注意行尾输出换行。*/ int main() { char *a = "I love China!"; int n; scanf("%d", &n); puts(a + n); return 0; }
#include <cstdio> #include <cstring> /* 输入3个字符串,按从小到大的顺序输出。要求使用指针的方法进行处理。 输入 3行,每行一个用字符串。保证每一个字符串的长度不超过20。 输出 按从小到大的顺序输出这3个字符串,每一个字符串一行. */ void swap(char s[], char a[]) { char t[30]; strcpy(t, s); strcpy(s, a); strcpy(a, t); } int main() { char a[30], b[30], c[30]; gets(a); gets(b); gets(c); if (strcmp(a, b) > 0) swap(a, b); if (strcmp(a, c) > 0) swap(a, c); if (strcmp(b, c) > 0) swap(b, c); puts(a); puts(b); puts(c); return 0; }
#include <cstdio> /*输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。要求 用3个函数实现,分别为输入10个数、进行处理、输出10个数。要求使用指针的方法进行处理。 输入 用空格隔开的10个整数。 输出 输出进行题目描述操做以后的10个整数,每一个整数以后输出一个空格。*/ void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void Input(int t[], int len) { for (int i = 0; i < len; i++) scanf("%d", t + i); } void Deal(int t[], int len) { int min , max, minK, maxK; min = max = t[0]; for (int i = 1; i < len; i++) { if (t[i] > max) { max = t[i]; maxK = i; } if (t[i] < min) { min = t[i]; minK = i; } } swap(t, t + minK); swap(t + 9, t + maxK); } void Print(int t[], int len) { for (int i = 0; i < len-1; i++) printf("%d ", t[i]); printf("%d", t[9]); } int main() { int a[11]; Input(a, 10); Deal(a, 10); Print(a, 10); return 0; }
#include <cstdio> #include <cstring> /* 输入第一行有一个整数n,表示如下有n张选票信息将会输入。保证n不大于100。 之后的n行中,每一行包含一我的名,为选票的得票人。保证每个人名都是Li, Zhang和Fun中的某一个。 输出 有三行,分别为Li,Zhang和Fun每人的得票数。格式为首先输出人名,其后输出一个冒号, 最后输出候选人的得票数。注意行尾输出换行。*/ struct person { char name[20]; int count; } leader[3] = {"Li", 0, "Zhang", 0, "Fun", 0}; int main() { int N; scanf("%d", &N); for (int i = 0; i <= N; i++) { char s[10]; gets(s); if (!strcmp(s, leader[0].name)) leader[0].count++; else if (!strcmp(s, leader[1].name)) leader[1].count++; else if (!strcmp(s, leader[2].name)) leader[2].count++; } for (int i = 0; i < 3; i++) printf("%s:%d\n", leader[i].name, leader[i].count); return 0; }
#include <cstdio> #include <cstring> /* 输入 第一行有一个整数n,表示如下有n个学生的信息将会输入。保证n不大于20。 之后的n行中,每一行包含对应学生的学号、名字、性别和年龄,用空格隔开。保证每个人名 都不包含空格且长度不超过15,性别用M和F两个字符来表示。 输出 有n行,每行输出一个学生的学号、名字、性别和年龄,用空格隔开。*/ struct student { int num; char name[20]; char sex; int age; }; int main() { int n; scanf("%d", &n); int i; struct student stus[n], *ptrToStus[n]; for (i = 0; i < n; i++) { scanf("%d %s %c %d", &stus[i].num, stus[i].name, &stus[i].sex, &stus[i].age); ptrToStus[i] = &stus[i]; } for (i = 0; i < n; i++) { printf("%d %s %c %d\n", ptrToStus[i]->num, ptrToStus[i]->name, ptrToStus[i]->sex, ptrToStus[i]->age); } return 0; }
很久没有用共用体了,并且就隔了两天,这么简单的东西都会写错,汗颜。算法
#include <cstdio> struct Job{ int num; char name[10]; char sex; char job; union { int Class; char position[10]; } category; }; int main() { int n; scanf("%d", &n); Job info[n]; for (int i = 0; i < n; i++) { scanf("%d %s %c %c", &info[i].num, info[i].name, &info[i].sex, &info[i].job); if (info[i].job == 's') scanf("%d", &info[i].category.Class); else if (info[i].job == 't') scanf("%s", info[i].category.position); } for (int i = 0; i < n; i++) { printf("%d %s %c %c ", info[i].num, info[i].name, info[i].sex, info[i].job); if (info[i].job == 's') printf("%d\n", info[i].category.Class); else if (info[i].job == 't') printf("%s\n", info[i].category.position); } return 0; }
#include <cstdio> typedef struct student { int num; char name[25]; int score1; int score2; int score3; } student; void input(student stds[]) { for (int i = 0; i < 5; i++) scanf("%d %s %d %d %d", &stds[i].num, stds[i].name, &stds[i].score1, &stds[i].score2, &stds[i].score3); } void print(student *stds) { for (int i = 0; i < 5; i++) printf("%d %s %d %d %d\n", stds[i].num, stds[i].name, stds[i].score1, stds[i].score2, stds[i].score3); } int main() { struct student stds[5]; input(stds); print(stds); return 0; }
#include <cstdio> typedef struct student { int num; char name[25]; int score1; int score2; int score3; } student; void input(student stds[]) { for (int i = 0; i < 10; i++) scanf("%d %s %d %d %d", &stds[i].num, stds[i].name, &stds[i].score1, &stds[i].score2, &stds[i].score3); } void print(student *stds) { double sum1 = 0, sum2 = 0, sum3 = 0, max_aver = (stds[0].score1 + stds[0].score2 + stds[0].score3) / 3.0, N = 10.0; int k = 0; for (int i = 0; i < 10; i++) { sum1 += stds[i].score1; sum2 += stds[i].score2; sum3 += stds[i].score3; double now_max = (stds[i].score1 + stds[i].score2 + stds[i].score3) / 3.0; if ( now_max > max_aver) { k = i; max_aver = now_max; } } printf("%.2f %.2f %.2f \n", sum1 / N, sum2 / N, sum3 / N); printf("%d %s %d %d %d\n", stds[k].num, stds[k].name, stds[k].score1, stds[k].score2, stds[k].score3); } int main() { struct student stds[10]; input(stds); print(stds); return 0; }
多点测试中有以下结构用于反复执行程序的核心部分:api
while-EOF类型
:如while (scanf("%d", &a) != EOF)
;while (scanf("%s", s) != EOF)
;while (gets(str) != NULL)
等用于输入字符串和数值。如题1。while-EOF-break
类型:输入数据知足某个条件时退出,如while (scanf("%d %d", &a, &b) != EOF, a | b)
。如题3。while (T--)
类型,给出测试数据的组数。如题2。#include <cstdio> int main() { int a, b; while (scanf("%d %d", &a, &b) == 2) // while (scanf("%d %d", &a, &b) != EOF) printf("%d\n", a + b); return 0; }
/* 输入 第一行是一个整数N,表示后面会有N行a和b,经过空格隔开。 输出 对于输入的每对a和b,你须要在相应的行输出a、b的和。 */ #include <cstdio> int main() { int a, b, T; scanf("%d", &T); while (T--) { scanf("%d %d", &a, &b); printf("%d\n", a + b); } return 0; }
/* 输入 输入中每行是一对a和b。其中会有一对是0和0标志着输入结束,且这一对不要计算。 输出 对于输入的每对a和b,你须要在相应的行输出a、b的和。*/ #include <cstdio> int main() { int a, b; while (scanf("%d%d", &a, &b), a || b) printf("%d\n", a + b); return 0; }
/*输入 每行的第一个数N,表示本行后面有N个数。 若是N=0时,表示输入结束,且这一行不要计算。*/ #include <cstdio> int r[100]; int main() { int sum = 0, N, a, i = 0; scanf("%d", &N); while (N) { while (N--) { scanf("%d", &a); sum += a; } r[i++] = sum; scanf("%d", &N); sum = 0; } for (int j = 0; j < i; j++) printf("%d\n", r[j]); return 0; }
/* 输入的第一行是一个正数N,表示后面有N行。每一行的第一个数是M,表示本行后面还有M个数。*/ #include <cstdio> int r[100]; int main() { int N, M, i = 0; scanf("%d", &N); while (N--) { scanf("%d", &M); int sum = 0, a; while (M--) { scanf("%d", &a); sum += a; } r[i++] = sum; sum = 0; } for (int j = 0; j < i; j++) printf("%d\n", r[j]); return 0; }
#include <cstdio> int r[100]; int main() { int sum = 0, N, a, i = 0; while (scanf("%d", &N) != EOF) { while (N--) { scanf("%d", &a); sum += a; } r[i++] = sum; sum = 0; } for (int j = 0; j < i; j++) printf("%d\n", r[j]); return 0; }
#include <cstdio> int main() { int a, b; while (scanf("%d%d", &a, &b) != EOF) printf("%d\n\n", a + b); return 0; }
#include <cstdio> int r[100]; int main() { int N, M, i = 0; scanf("%d", &N); while (N--) { int sum = 0, a; scanf("%d", &M); while (M--) { scanf("%d", &a); sum += a; } r[i++] = sum; sum = 0; } for (int j = 0; j < i; j++) printf("%d\n\n", r[j]); return 0; }
简单模拟这类题目不涉及算法,彻底只是根据题目描述来进行代码的编写。数组
#include <cstdio> #include <cstring> /*有一个长度为整数L(1<=L<=10000)的马路,想象成数轴上长度为L的一个线段,起点是坐标原点, 在每一个整数坐标点有一棵树,即在0,1,2,...,L共L+1个位置上有L+1棵树。 如今要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)全部的树。 可能有M(1<=M<=100)个区间,区间之间可能有重叠。如今要求移走全部区间的树以后剩下的树的个数。 输入 两个整数L(1<=L<=10000)和M(1<=M<=100)。接下来有M组整数,每组有一对数字。输入0 0表示结束。 输出 可能有多组输入数据,对于每组输入数据,输出一个数,表示移走全部区间的树以后剩下的树的个数。*/ int main() { int r[200], j = 0; memset(r, 0, sizeof(r)); int L, M; int left, right; while (scanf("%d%d", &L, &M), L) { int a[L+1]; memset(a, 0, sizeof(a)); while (M--) { scanf("%d%d", &left, &right); for (int i = left; i <= right; i++) { a[i] = 1; } } for (int i = 0; i <= L; i++) if (!a[i]) r[j]++; j++; } for (int i = 0; i < j; i++) { printf("%d\n", r[i]); } return 0; }
/*给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开。 输入 输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-10^9 < A,B < 10^9)。 输出 请计算A+B的结果,并以正常形式输出,每组数据占一行。*/ #include <cstdio> #include <cstring> long long to_int(char s[]) { int len = strlen(s); long long r = 0; int positive = 1; for (int i = 0; i < len; i++) { //','就直接跳过 if (s[i] <= '9' && s[i] >= '0') { r = r * 10 + (s[i] - '0'); } else if (s[i] == '-') positive = 0; } if (!positive) r = -r; return r; } int main() { char s[50], r[50]; while (scanf("%s %s", s, r) != EOF) { long long snum, rnum; snum = to_int(s); rnum = to_int(r); printf("%lld\n", snum + rnum); } return 0; }
/*写个算法,对2个小于1000000000的输入,求结果。特殊乘法举例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5 输入 两个小于1000000000的数 输出 输入可能有多组数据,对于每一组数据,输出两个数按照题目要求的方法进行运算后获得的结果。*/ #include <cstdio> int int_to_array(int n, int num[]) { int i = 0; while (n) { num[i++] = n % 10; n /= 10; } return i; } int specialMulti(int num1[], int num2[], int len1, int len2) { int sum = 0; for (int i = 0; i < len1; i++) { for (int j = 0; j < len2; j++) { sum += (num1[i] * num2[j]); } } return sum; } int main() { int M, N; int numM[15], numN[15], lenM, lenN; while (scanf("%d%d", &M, &N) != EOF) { lenM = int_to_array(M, numM); lenN = int_to_array(N, numN); printf("%d\n", specialMulti(numM, numN, lenM, lenN)); } return 0; }
/* 输入 输入有多组数据。每组输入n,而后输入n个整数(1<=n<=1000)。 输出 若是偶数比奇数多,输出NO,不然输出YES。*/ #include <cstdio> int main() { int N, a, odd, even; odd = even = 0; while (scanf("%d", &N) != EOF) { while (N--) { scanf("%d", &a); if (a % 2) odd++; else even++; } if (even > odd) printf("NO\n"); else printf("YES\n"); } return 0; }
题目描述
The task is really simple: given N exits on a highway which forms a simple cycle,
you are supposed to tell the shortest distance between any pair of exits.数据结构
输入
Each input file contains one test case. For each case, the first line contains an
integer N (in [3, 105]), followed by N integer distances D1 D2 … DN, where Di
is the distance between the i-th and the (i+1)-st exits, and DN is between the
N-th and the 1st exits. All the numbers in a line are separated by a space.
The second line gives a positive integer M (<=104), with M lines follow, each
contains a pair of exit numbers, provided that the exits are numbered from 1 to
N. It is guaranteed that the total round trip distance is no more than 107.
输出
For each test case, print your results in M lines, each contains the shortest
distance between the corresponding given pair of exits.
样例输入
5 1 2 4 14 9 3 1 3 2 5 4 1
样例输出
3 10 7
#include <cstdio> int RightDistance(int a[], int left, int right) { // [left, right) int sum = 0; for (int i = left - 1; i < right - 1; i++) // 逻辑序号映射到物理序号 sum += a[i]; return sum; } int LeftDistance(int a[], int N, int rightDist) { int sum = 0; for (int i = 0; i < N; i++) sum += a[i]; return sum - rightDist; // 环的性质 } int main() { int N, M; while (scanf("%d", &N) != EOF) { int a[N]; for (int i = 0; i < N; i++) { scanf("%d", &a[i]); } scanf("%d", &M); int left, right; while (M--) { scanf("%d%d", &left, &right); int r1, r2; if (left > right) r1 = RightDistance(a, right, left); // 改变方向 else r1 = RightDistance(a, left, right); r2 = LeftDistance(a, N, r1); printf("%d\n", r1 < r2 ? r1 : r2); } } return 0; }
这题用int会溢出,干脆使用long long。除非这样也不行,就用大整数结构。
/*题目描述 给定区间[-2^31, 2^31]内的3个整数A、B和C,请判断A+B是否大于C。 输入 输入第1行给出正整数T(<=10),是测试用例的个数。随后给出T组测试用例,每组占一行, 顺序给出A、B和C。整数间以空格分隔。 输出 对每组测试用例,在一行中输出“Case #X: true”若是A+B>C,不然输出“Case #X: false”,其中X是 测试用例的编号(从1开始)。 */ #include <cstdio> int main() { int T; scanf("%d", &T); for (int i = 1; i <= T; i++) { long long a, b, c; scanf("%lld%lld%lld", &a, &b, &c); if (a + b > c) printf("Case #%d: true\n", i); else printf("Case #%d: false\n", i); } return 0; }
给定一系列正整数,请按要求对数字进行分类,并输出如下5个数字:
输入
每一个输入包含1个测试用例。每一个测试用例先给出一个不超过1000的正整数N,随后给出N个
不超过1000的待分类的正整数。数字间以空格分隔。
输出
对给定的N个正整数,按题目要求计算A1~A5并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。若其中某一类数字不存在,则在相应位置输出“N”。
这题原本简单,就是要求输出N的判断麻烦,可能会栽在这里。
#include <cstdio> int main() { int N, a; int a1, a2, a3, a5, n; double a4; int b1, b2, b5; while (scanf("%d", &N) != EOF) { a1 = a2 = a3 = a4 = a5 = n = b1 = b2 = b5 = 0; int flag = 1; for (int i = 0; i < N; i++) { scanf("%d", &a); switch (a % 5) { case 0: if (a % 2 == 0) { a1 += a; b1++; } break; case 1: if (flag) { a2 += a; b2++; flag = 0; } else { a2 += -a; b2++; flag = 1; } break; case 2: a3++; break; case 3: a4 += a; n++; break; case 4: if (a > a5) a5 = a; b5++; break; } } if (b1) printf("%d ", a1); else printf("N "); if (b2) printf("%d ", a2); else printf("N "); if (a3) printf("%d ", a3); else printf("N "); if (n) printf("%.1f ", (double)a4 / n); else printf("N "); if (b5) printf("%d\n", a5); else printf("N\n"); } return 0; }
正整数A的“DA(为1位整数)部分”定义为由A中全部DA组成的新整数PA。例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,由于A中有2个6。
现给定A、DA、B、DB,请编写程序计算PA + PB。
#include <cstdio> #include <cstring> /* 给出字符如'6'出现n次的数字, n=1时为6 */ int charToNum(char d, int n) { int numD = d - '0', res = 0; for (int i = 0; i < n; i++) { res = (res * 10 + numD); } return res; } int main() { char a[25], b[25]; char da, db; while (scanf("%s %c %s %c", a, &da, b, &db) != EOF) { int len1 = strlen(a), len2 = strlen(b), n1 = 0, n2 = 0; for (int i = 0; i < len1; i++) if (a[i] == da) n1++; for (int i = 0; i < len2; i++) if (b[i] == db) n2++; printf("%d\n", charToNum(da, n1) + charToNum(db, n2)); } return 0; }
你们应该都会玩“锤子剪刀布”的游戏:两人同时给出手势。现给出两人的交锋记录,请统计
双方的胜、平、负次数,而且给出双方分别出什么手势的胜算最大。
本题我发现对于scanf("%c")的用法容易出错,此时会将空格和换行符一并输入,所以须要用getchar()吸取。
#include <cstdio> #include <cstring> char c[] = {'B', 'C', 'J'}; /* 返回获胜次数最多的手势,若是解不惟一,则返回按字母序最小的手势字符 */ char checkWinWay(int m[]) { int k = 0; for (int i = 1; i < 3; i++) if (m[i] > m[k]) k = i; return c[k]; } int main() { int N, winJ, winY, par, J[3], Y[3]; winJ = winY = par = 0; memset(J, 0, sizeof(J)); // B C J memset(Y, 0, sizeof(Y)); char a, b; scanf("%d", &N); getchar(); // 吸取换行 for (int i = 0; i < N; i++) { scanf("%c", &a); getchar(); // 吸取空格 scanf("%c", &b); getchar(); // 吸取换行 switch(a) { case 'C': switch(b) { case 'C': par++; break; case 'J': winJ++; J[1]++; break; case 'B': winY++; Y[0]++; break; } break; case 'J': switch(b) { case 'C': winY++; Y[1]++; break; case 'J': par++; break; case 'B': winJ++; J[2]++; break; } break; case 'B': switch(b) { case 'C': winJ++; J[0]++; break; case 'J': winY++; Y[2]++; break; case 'B': par++; break; } break; } } printf("%d %d %d\n%d %d %d\n", winJ, par, N-winJ-par, winY, par, N-winY-par); printf("%c %c\n", checkWinWay(J), checkWinWay(Y)); return 0; }
http://codeup.cn/contest.php?cid=100000576
这一题须要用输入的人数N做为循环判断条件。
/*读入N名学生的成绩,将得到某一给定分数的学生人数输出。 输入 每一个测试用例的格式为 第1行:N 第2行:N名学生的成绩,相邻两数字用一个空格间隔。 第3行:给定分数 当读到N=0时输入结束。其中N不超过1000,成绩分数为(包含)0到100之间的一个整数。 输出 对每一个测试用例,将得到给定分数的学生人数输出。 */ #include <cstdio> int main() { int N; while (scanf("%d", &N), N) { int a[N]; for (int i = 0; i < N; i++) scanf("%d", &a[i]); int num, cnt = 0; scanf("%d", &num); for (int i = 0; i < N; i++) if (a[i] == num) cnt++; printf("%d\n", cnt); } return 0; }
/*输入一个数n,而后输入n个数值各不相同,再输入一个值x,输出这个值在这个数组中的下标(从0开始,若不在数组中则输出-1)。 输入 测试数据有多组,输入n(1<=n<=200),接着输入n个数,而后输入x。 输出 对于每组输入,请输出结果。 */ #include <cstdio> int main() { int N; while (scanf("%d", &N) != EOF) { int a[N]; for (int i = 0; i < N; i++) scanf("%d", &a[i]); int num, index; scanf("%d", &num); int flag = 1; for (int i = 0; i < N; i++) if (a[i] == num) { flag = 0; printf("%d\n", i); break; } if (flag) printf("%d\n", -1); } return 0; }
CodeUp是多点测试的,居然忘记了这个状况!同时,在对字符串申请空间时,尽可能多申请一点。
#include <cstdio> #include <cstring> typedef struct student { char index[5]; char name[100]; char sex[10]; int age; } student; student stu[1010]; int main() { int N; while (scanf("%d", &N) != EOF) { for (int i = 0; i < N; i++) scanf("%s %s %s %d", stu[i].index, stu[i].name, stu[i].sex, &stu[i].age); int M; scanf("%d", &M); while (M--) { char in[10]; scanf("%s", in); int i; for (i = 0; i < N; i++) { if (strcmp(stu[i].index, in) == 0) { printf("%s %s %s %d\n", stu[i].index, stu[i].name, stu[i].sex, stu[i].age); break; } } if (i == N) printf("No Answer!\n"); } } return 0; }
/*输入数组长度 n 输入数组 a[1...n] 输入查找个数m 输入查找数字b[1...m] 输出 YES or NO 查找有则YES 不然NO 。 输入 输入有多组数据。 每组输入n,而后输入n个整数,再输入m,而后再输入m个整数(1<=m<=n<=100)。 输出 若是在n个数组中输出YES不然输出NO。 */ #include <cstdio> int main() { int n; while (scanf("%d", &n) != EOF) { int a[150]; for (int i = 0; i < n; i++) scanf("%d", &a[i]); int m; scanf("%d", &m); while (m--) { int num, i; scanf("%d", &num); for (i = 0; i < n; i++) if (a[i] == num) { printf("YES\n"); break; } if (i == n) printf("NO\n"); } } return 0; }
/* 输入n个学生的信息,每行包括学号、姓名、性别和年龄,每个属性使用空格分开。 最后再输入一学号,将该学号对应的学生信息输出。 输入 测试数据有多组,第一行为样例数m。对于每一个样例,第一行为学生人数n(n不超过20), 加下来n行每行4个整数分别表示学号、姓名、性别和年龄,最后一行表示查询的学号。 输出 输出m行,每行表示查询的学生信息,格式参见样例。 */ #include <cstdio> typedef struct student { int index; char name[100]; char sex[10]; int age; } student; student stu[50]; int main() { int m; scanf("%d", &m); while (m--) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d %s %s %d", &stu[i].index, stu[i].name, stu[i].sex, &stu[i].age); int in; scanf("%d", &in); int i; for (i = 0; i < n; i++) { if (stu[i].index == in) { printf("%d %s %s %d\n", stu[i].index, stu[i].name, stu[i].sex, stu[i].age); break; } } } return 0; }
输入一个高度h,输出一个高为h,上底边为h的梯形。
样例输入
5
样例输出
***** ******* ********* *********** *************
这个题目也是多点测试的,别看它题目说是“一个”。
#include <cstdio> int main() { int h; while (scanf("%d", &h) != EOF) { int UpEdge = h, DownEdge = 3 * h - 2; for (int i = UpEdge; i <= DownEdge; i += 2) { int spaceNum = DownEdge - i; for (int j = 1; j <= spaceNum; j++) printf(" "); for (int k = 1; k <= i; k++) printf("*"); printf("\n"); } } return 0; }
Given any string of N (>=5) characters, you are asked to form the characters into the shape of U.
That is, the characters must be printed in the original order, starting top-down from the left vertical
line with n1 characters, then left to right along the bottom line with n2 characters, and finally bottom-up
along the vertical line with n3 characters. And more, we would like U to be as squared as possible – that is,
it must be satisfied that n1 = n3 = max { k| k <= n2 for all 3 <= n2 <= N } with n1 + n2 + n3 - 2 = N
.
helloworld!
h ! e d l l lowor
这一题须要解决的问题是将一个字符串写成U字形。拿到这一题的第一映像是U字的写法,先是写第一排第一个字符,而后写第二排第一个字符……而后是最后一排,而后是倒数第二排……但在C语言中若是咱们要这
样写U字形的字符串就须要在数组中操做了。若是是直接输出的话,那只能自上至下一行一行输出。首先是第一行,写出第一个字符和最后一个字符,第二行写出第二个字符和倒数第二个字符……最后是最后一行。须要注意的是除了最后一行输出全部字符,前面每一行只输出两个字符。中间还有空格来隔开每行的两个字符。
思路有了,看看具体的要求。字符串的长度是N,n1,n3表明两边每列字符的数目。n2表明最后一行的字符数。题目中给了一个算式:
n1 = n3 = max { k| k <= n2 for all 3 <= n2 <= N } with n1 + n2 + n3 - 2 = N.
仔细研究这个算式,这里的k是不大于n2的,也就是说n1和n3是不大于n2且知足n1+n2+n3=N+2的最大值。相似于将字符串长度增长2再对折成三段
。那么天然有n1=n3=(N+2)/3,n2=N+2-(n1+n3)
。
也就是说设side为两边的字符数(包括最后一行的两端),则side=n1=n3=(N+2)/3
。设mid为最后一行除去两端的两个字符后剩下的字符数,mid=N-side*2
(总长度减去两边的字符数)。同时mid也是咱们输出除最后一行外前面全部行须要空出的空格数。
最后,如何在第i行输出第一个字符和最后一个字符呢?那天然是str[i]和str[len-1-i]
(len为字符串的长度,也就是N)。具体细节详见代码。
因而问题完美解决,步骤以下:
1)计算字符串长度len;
2)计算两边的字符数side=(len+2)/3;
3)计算最后一行中间的字符数(前面每行中间的空格数)
4)输出每行相应的字符。
#include <cstdio> #include <cstring> int main() { char s[100]; int side, mid, len; while (scanf("%s", s) != EOF) { len = strlen(s); side = (len + 2) / 3; mid = len - side * 2; for (int i = 0; i < side; i++) { if (i < side - 1) { //输出除最后一行的前面全部行 printf("%c", s[i]); for (int j = 0; j < mid; j++) printf(" "); printf("%c\n", s[len - 1 - i]); } else if (i == side - 1) { //输出最后一行 for (int j = 0; j < mid + 2; j++) printf("%c", s[i++]); printf("\n"); } } } return 0; }
请输入高度h,输入一个高为h,上底边长为h 的等腰梯形。
1 4
样例输出
**** ****** ******** **********
这题与上上题的打印梯形有很大联系,只是变化了一下。
#include <cstdio> int main() { int m, h; scanf("%d", &m); while (m--) { scanf("%d", &h); int UpEdge = h, DownEdge = 3 * h - 2; for (int i = UpEdge; i <= DownEdge; i += 2) { //打印空格 int spaceNum = (DownEdge - i) / 2; for (int j = 0; j < spaceNum; j++) printf(" "); //打印等腰梯形主体 for (int k = 0; k < i; k++) printf("%c", '*'); printf("\n"); } } return 0; }
问题:输入n,输出正倒n层星号三角形。首行顶格,星号间有一空格,效果见样例
输入样例:
3
输出样例:
* * * * * * * * * * *
数据规模 1<= n <=50
#include <cstdio> int main() { int n; while (scanf("%d", &n) != EOF) { //打印上半部分 int UpEdge = n + n - 1; //第一层的字符数(包括空格和星号) for (int i = UpEdge; i >= n; i--) { //i表示每层所拥有的字符数 int spaceNum = UpEdge - i; for (int j = 0; j < spaceNum; j++) printf(" "); int charNum = i - n + 1; for (int j = 0; j < charNum - 1; j++) printf("* "); printf("*\n"); } //打印下半部分 for (int i = n + 1; i <= UpEdge; i++) { int spaceNum = UpEdge - i; for (int j = 0; j < spaceNum; j++) printf(" "); int charNum = i - n + 1; for (int j = 0; j < charNum - 1; j++) printf("* "); printf("*\n"); } } return 0; }
http://codeup.cn/contest.php?cid=100000578
题目描述:有两个日期,求两个日期之间的天数,若是两个日期是连续的咱们规定他们之间的天数为两天。
#include <cstdio> int month[13][2] = { //平年闰年的每月天数(月/日), 第一行平年, 第二行闰年 {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义 }; bool isLeap(int year) { //判断是不是闰年 return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); } int main() { int time1, y1, m1, d1; int time2, y2, m2, d2; while (scanf("%d%d", &time1, &time2) != EOF) { //scanf(%d)会忽视空格和换行 if (time1 > time2) { //若是time1晚于time2则交换, 使第一个日期早于第二个日期 int temp = time1; time1 = time2; time2 = temp; } y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100; y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100; int ans = 1; //记录日期差值, 由于连续两个日期天数为两天, 因此初值为1 /* 第一个日期没有达到第二个日期时循环 */ while (y1 < y2 || m1 < m2 || d1 < d2) { d1++; if (d1 == month[m1][isLeap(y1)] + 1) { //满当月天数 d1 = 1; //日期变为下个月的1号 m1++; //月份+1 } if (m1 == 13) { //月份满12个月 m1 = 1; //月份变为下一年的1月 y1++; //年+1 } ans++; //累计 } printf("%d\n", ans); } return 0; }
We now use the Gregorian style of dating in Russia. The leap years are years with number divisible
by 4 but not divisible by 100, or divisible by 400.
For example, years 2004, 2180 and 2400 are leap. Years 2004, 2181 and 2300 are not leap.
Your task is to write a program which will compute the day of week corresponding
to a given date in the nearest past or in the future using today’s agreement about dating.
21 December 2012 5 January 2013
Friday Saturday
这么写只有50%?!不知道问题出在哪里……不过不少日期问题的实质就是在花式数天数。
#include <cstdio> #include <cstring> struct Date{ int y, m, d; }; char MonthName[13][12]= {"None", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; char Weekday[8][12] = {"None", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; int mapMonth(char s[]) { for (int i = 1; i < 13; i++) { if (strcmp(s, MonthName[i]) == 0) return i; } return 0; } int month[13][2] = { //平年闰年的每月天数(月/日), 第一行平年, 第二行闰年 {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义 }; bool isLeap(int year) { //判断是不是闰年 return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); } bool MoreEqu(struct Date day1, struct Date day2) { //若是第一个日期晚(大)于第二个日期, 返回true if (day1.y != day2.y) return day1.y >= day2.y; else if (day1.m != day2.m) return day1.m >= day2.m; else return day1.d >= day2.d; } int main() { struct Date MyDay, now = {2019, 7, 29}; char mEnglish[14]; while (scanf("%d%s%d", &MyDay.d, mEnglish, &MyDay.y) != EOF) { MyDay.m = mapMonth(mEnglish); int flag = 0; struct Date tmp = now; if (MoreEqu(MyDay, now)) { struct Date t = MyDay; MyDay = tmp; tmp = t; flag = 1; } int cnt = 0; while (MyDay.y < tmp.y || MyDay.m < tmp.m || MyDay.d < tmp.d) { MyDay.d++; cnt++; if (MyDay.d == month[MyDay.m][isLeap(MyDay.y)] + 1) { MyDay.m++; MyDay.d = 1; } if (MyDay.m == 13) { MyDay.y++; MyDay.m = 1; } } int offset = cnt % 7; // x if (flag) printf("%s\n", Weekday[1 + offset]); // x else printf("%s\n", Weekday[1 - offset + 7]); // x } return 0; }
我知道错误了,小于20190729的每隔7天的日期(星期一)没法成功输出。把上面的最后标记的几句改为下面这样就能够了:
if (!flag) cnt = - cnt; int offset = ((cnt % 7) + 7) % 7; printf("%s\n", Weekday[1 + offset]);
或者打个补丁:
int offset = cnt % 7; //22 July 2019 if (flag) printf("%s\n", Weekday[1 + offset]); else { if (offset) printf("%s\n", Weekday[8 - offset]); else printf("%s\n", Weekday[1]); }
换种数法,计算从公元到输入日期的天数好了,而后与标的日期天数相减。数的时候先数年再数月再很多天,加快速度。这样节省了一点代码。
#include <cstdio> #include <cstring> struct Date { int y, m, d; }; char MonthName[13][12]= {"None", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; char Weekday[8][12] = {"None", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; int month[13][2] = { //平年闰年的每月天数(月/日), 第一行平年, 第二行闰年 {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义 }; int mapMonth(char s[]) { for (int i = 1; i < 13; i++) { if (strcmp(s, MonthName[i]) == 0) return i; } return 0; } bool isLeap(int year) { //判断是不是闰年 return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); } int sumDays(struct Date tmp) { int day = 0; for (int i = 0; i < tmp.y; i++) { day += (isLeap(i) ? 366 : 365); } for (int i = 1; i < tmp.m; i++) { day += month[i][isLeap(tmp.y)]; } for (int i = 1; i < tmp.d; i++) { day++; } return day; // 737634 } int main() { struct Date MyDay; // now = {2019, 7, 29}; 距离公元元年737634天 char mEnglish[14]; while (scanf("%d%s%d", &MyDay.d, mEnglish, &MyDay.y) != EOF) { MyDay.m = mapMonth(mEnglish); int dayCount = sumDays(MyDay) - 737634; //获得日期差值 int offset = ((dayCount % 7) + 7) % 7; //对负数和超出的正数修正 printf("%s\n", Weekday[1 + offset]); //1-7 20190729星期一 } return 0; }
题目描述:给出年分m和一年中的第n天,算出第n天是几月几号。
2013 60 2012 300 2011 350 2000 211
2013-03-01 2012-10-26 2011-12-16 2000-07-29
将天数翻译成对应年的第几天,这个问题跟A.日期差值
是基本同样的,只是这题不是比较两个日期的差异,而是用一个累加器,每过一天+1,与输入的一年中第几天比较,不断循环。
#include <cstdio> int month[13][2] = { //平年闰年的每月天数(月/日), 第一行平年, 第二行闰年 {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义 }; bool isLeap(int year) { //判断是不是闰年 return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); } int main() { int year, day; while (scanf("%d%d", &year, &day) != EOF) { int y = year, m = 1, d = 1, cnt = 1; //cnt计数, 表示第几天 while (cnt < day) { d++; if (d == month[m][isLeap(y)] + 1) { m++; d = 1; } cnt++; } printf("%04d-%02d-%02d\n", y, m, d); } return 0; }
题目描述:编写一个日期类,要求按xxxx-xx-xx 的格式输出日期,实现加一天的操做。
2 1999 10 20 2001 1 31
1999-10-21 2001-02-01
#include <cstdio> int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int main() { int M; scanf("%d", &M); int y, m, d; for (int i = 0; i < M; i++) { scanf("%d%d%d", &y, &m, &d); d++; if (d == month[m] + 1) { m++; d = 1; } printf("%04d-%02d-%02d\n", y, m, d); } return 0; }
题目描述:设计一个程序能计算一个日期加上若干天后是什么日期。
1 2008 2 3 100
2008-05-13
与A.日期差值
不少同样的代码,或者说日期类的题目,平年闰年、大月小月的分辨就是基础了。
这一题是上一题D.日期类
的深刻,上一题只要求+1天,无闰年,而这一题就不同了。可是大致上仍是同样的思路。
#include <cstdio> int month[13][2] = { //平年闰年的每月天数(月/日), 第一行平年, 第二行闰年 {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义 }; bool isLeap(int year) { //判断是不是闰年 return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); } int main() { int M; scanf("%d", &M); int y, m, d, days; while (M--) { scanf("%d %d %d %d", &y, &m, &d, &days); int cnt = 0; //表示已增长的天数, 与days比较作循环 while (cnt < days) { d++; if (d == month[m][isLeap(y)] + 1) { m++; d = 1; } if (m == 13) { y++; m = 1; } cnt++; } printf("%04d-%02d-%02d\n", y, m, d); } return 0; }
获得某一日期距离公元元年的天数。
struct Date { int y, m, d; }; int sumDays(struct Date tmp) { int reDay = 0; struct Date Gen = {0, 1, 1}; while (Gen.y < tmp.y || Gen.m < tmp.m || Gen.d < tmp.d) { Gen.d++; reDay++; if (Gen.d == month[Gen.m][isLeap(Gen.y)] + 1) { Gen.m++; Gen.d = 1; } if (Gen.m == 13) { Gen.y++; Gen.m = 1; } } return reDay; }
int sumDays(struct Date tmp) { int day = 0; for (int i = 0; i < tmp.y; i++) { //先数年 day += (isLeap(i) ? 366 : 365); } for (int i = 1; i < tmp.m; i++) { //再数月 day += month[i][isLeap(tmp.y)]; } for (int i = 1; i < tmp.d; i++) { //再很多天 day++; } return day; }
http://codeup.cn/contest.php?cid=100000579
进制转换的基础主要是10进制转换为R进制和R进制转换为10进制
,掌握这两个代码片就能够了。P进制转换为Q进制是这两个过程的统合,经过十进制做为中转站。
/* 输入两个不超过整型定义的非负10进制整数A和B(<=231-1),输出A+B的m (1 < m <10)进制数。 输入:测试输入包含若干测试用例。每一个测试用例占一行,给出m和A,B的值。当m为0时输入结束。 输出:每一个测试用例的输出占一行,输出A+B的m进制数。 */ #include <cstdio> int main() { long long a, b, sum; int m, nums[50]; while (scanf("%d", &m), m) { scanf("%lld%lld", &a, &b); sum = a + b; int i = 0; /* 10进制转换为R进制的代码片 */ do { nums[i++] = sum % m; sum /= m; } while (sum != 0); //倒着打印 for (int j = i - 1; j >= 0; j--) { printf("%d", nums[j]); if (j == 0) printf("\n"); } } return 0; }
题目描述:求任意两个不一样进制非负整数的转换(2进制~16进制),所给整数在long所能表达的范围以内。不一样进制的表示符号为(0,1,…,9,a,b,…,f)或者(0,1,…,9,A,B,…,F)。
4 123 10
27
这一题的关键在于要用字符串存储和表示不一样进制的数,由于输入的数为a进制,多是16进制,会使用a-f或A-F的字符,并且输出的数也可能有字母。能够说,这一题就是比较通用的2-16进制非负整数间的转换程序。
#include <cstdio> #include <cstring> int CharToOct(int a, char n[]) { //按进制a将n字符串(可表示2-16进制)转换为10进制数 int sum = 0, product = 1; for (int i = strlen(n) - 1; i >= 0; i--) { if (n[i] <= '9') sum += (n[i] - '0') * product; else if (n[i] <= 'F') sum += (n[i] - 'A' + 10) * product; //大写字母符号 else if (n[i] <= 'f') sum += (n[i] - 'a' + 10) * product; //小写字母符号 product *= a; } return sum; } void OctToChar(int temp, int b, char r[]) { //将10进制数按b进制转换成r字符串 int i = 0; do { int k = temp % b; if (k <= 9) r[i++] = '0' + k; //十进制符号 else r[i++] = 'A' + k - 10; //用大写字母表示大于9的数字 temp /= b; } while (temp != 0); r[i] = '\0'; //必须添加结束符, 否则strlen没法正确判别长度 } int main() { int a, b; // 2-16 char n[100]; while (scanf("%d%s%d", &a, n, &b) != EOF) { int temp = CharToOct(a, n); if (b == 10) { printf("%d\n", temp); continue; } char r[100]; OctToChar(temp, b, r); for (int j = strlen(r) - 1; j >= 0; j--) printf("%c", r[j]); printf("\n"); } return 0; }
题目描述:将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。
985 211 1126
1111011001 11010011 10001100110
使用字符数组存储的时候,是逆位存储的,即整数低位存储在字符数组的高位,整数高位存储在字符数组的低位。虽然理顺了逻辑也很不错。
#include <cstdio> int main() { char s[32]; //将十进制字符串转换为倒排的二进制字符串, 需模拟屡次数字取余和除法 while (gets(s)) { char nums[100] = {}; int numsSize = 0, sum = 1; //全十进制字符串 while (sum) { //当十进制字符还未除完时继续循环 sum = 0; //每一次十进制字符串除以2都恢复0 for (int i = 0; s[i]; i++) { int digit = s[i] - '0'; int x = digit / 2; sum += x; if (s[i + 1]) { s[i + 1] += (digit % 2 * 10); } else { nums[numsSize++] = digit % 2 + '0'; //从低位向高位存入取余的字符 } s[i] = x + '0'; //一位字符的变化 } } for (int k = numsSize - 1; k >= 0; k--) { printf("%c", nums[k]); } printf("\n"); } return 0; }
#include <cstdio> int main() { int N, nums[50]; while (scanf("%d", &N) != EOF) { int i = 0; do { nums[i++] = N % 8; N /= 8; } while (N != 0); for (int j = i - 1; j >= 0; j--) printf("%d", nums[j]); printf("\n"); } return 0; }
#include <cstdio> int main() { char s1[200], s2[100], r[210]; while (scanf("%s%s", s1, s2) != EOF) { int i; for (i = 0; s1[i]; i++) { r[i] = s1[i]; } for (int j = 0; s2[j]; j++) { r[i++] = s2[j]; } r[i] = '\0'; puts(r); } return 0; }
if so, you already have a google account. you can sign in on the right.
If So, You Already Have A Google Account. You Can Sign In On The Right.
这个题其实很简单,PAT B1009说反话
与之相似,均可以用两种方法实现,一者是直接对字符串进行总体处理,是一种简单的办法,可是可能会写错。像这题就是将第一个字母和每一个空格符后面的字母变成大写,个人思路是这样,可是写的时候搞错判断了(主要是if条件太长),要对这些字母自己是否已是大写进行判断,否则就会出错。
#include <cstdio> int main() { char s[120]; while (gets(s) != NULL) { for (int i = 0; s[i]; i++) { if ( ((!i) || (s[i-1] == ' ' || s[i-1] == '\t' || s[i-1] == '\r' || s[i-1] == '\n')) && s[i] >= 'a' && s[i] <= 'z' ) s[i] -= ('a' - 'A'); // s[i] - 32 } puts(s); } return 0; }
第二种方法就是分割字符串成为一个个单词,这时省去对第一个字母进行特判,而后判断每一个单词的首字母自己是否已是大写,不是则变为大写,最后输出。这样麻烦一点。
并且CodeUp的判题机也有问题,有时候加个大括号就能够正确了……
#include <cstdio> int main() { char s[120]; while (gets(s) != NULL) { char words[100][100] = {}; int r = 0, c = 0; //分割字符串成多个单词 for (int i = 0; s[i]; i++) { if (s[i] != ' ' && s[i] != '\t' && s[i] != '\r' && s[i] != '\n') words[r][c++] = s[i]; else { words[r++][c] = '\0'; c = 0; } } //单词首字母大写 for (int j = 0; j <= r; j++) if (words[j][0] >= 'a') words[j][0] -= 32; //输出单词 for (int j = 0; j <= r; j++) { printf ("%s", words[j]); if (j < r) printf (" "); else printf ("\n"); } } return 0; }
题目描述:给定一个短字符串(不含空格),再给定若干字符串,在这些字符串中删除所含有的短字符串。
in #include int main() { printf(" Hi "); }
#clude tma() { prtf("Hi"); }
这个题目还有点难度,必须一口气输入全部字符串进行处理。个人代码以下:
判断逻辑:遍历字符串,某字符与短字符第一个字符相同;再判断下一位字符是否相同,直至彻底相同,彻底相同则跳过。
#include <cstdio> char del[1000], temp[1001][1001], ans[1001][1001]; int main() { int index = 0; gets(del); for (; gets(temp[index]) != NULL; index++); //读入数据 /* 将要删除的字符转为小写 */ for (int i = 0; del[i]; i++) { if (del[i] >= 'A' && del[i] <= 'Z') { del[i] += 32; } } for (int i = 0; i < index; i++) { int k; /* 用另外一二维数组存储原数据,而后将原数据转化为小写字母 */ for (k = 0; temp[i][k]; k++) { ans[i][k] = temp[i][k]; if (temp[i][k] >= 'A' && temp[i][k] <= 'Z') { temp[i][k] += 32; } } ans[i][k] = '\0'; //结束一句的复制 /* 进行短字符判断,若是不是短字符或空格就输出 */ for (int j = 0, len = 0; temp[i][j]; j++, len = 0) { //用len加以试探 while (temp[i][j + len] == del[len]) { //判断是否与短字符第一个字符相同, 相同则继续循环 len++; if (!del[len]) { //这一段与短字符彻底相同 j += len; //指向i行j列的指针跳过这一段 len = 0; //接着循环比较, 不一样则进入下面的if语句打印字符 } } if (temp[i][j] != ' ') printf("%c", ans[i][j]); } printf("\n"); //输出一句后的换行 } return 0; }
这一段的逻辑也能够这么写,二者等价:
for (int j = 0, len = 0; temp[i][j]; ) { if (temp[i][j + len] == del[len]) { len++; if (!del[len]) { //若彻底相同则跳过 j += len; //接着就能够开始下一个字符的判断 len = 0; } } else { // 不一样则进入下面的if语句打印字符 if (temp[i][j] != ' ') printf ("%c", ans[i][j]); //输出原字符 j++; //打印一个字符后j+1 len = 0; } } printf ("\n");
本题要求将s中全部单词a替换成b以后的字符串,若是真正替换很麻烦,因此这里先将字符串分割成单词组,而后对要替换的单词a,输出替换后的单词b。
#include <cstdio> #include <cstring> int main() { char s[120]; while (gets(s)) { char source[110] = {}, dest[110] = {}, words[110][50] = {}; gets(source); gets(dest); int r = 0, c = 0; for (int i = 0; s[i]; i++) { if (s[i] != ' ') { words[r][c++] = s[i]; } else { words[r++][c] = '\0'; c = 0; } } for (int j = 0; j <= r; j++) { if (strcmp(words[j], source) == 0) { printf("%s", dest); } else { printf("%s", words[j]); } if (j < r) printf(" "); else printf("\n"); } } return 0; }
这道题老是卡在50%上面。并且用scanf("%s\n%c", s, &c) != EOF
在个人电脑上能够正确运行,在网上就不能够了。因此有时仍是用gets和getchar()。
这里,我发现有时候不必定要使用strlen函数,直接用结束符判断就很好,这也是结束符的本意。
#include <cstdio> int main() { char s[1000], c; while (gets(s) != NULL) { c = getchar(); for (int i = 0; s[i]; i++) if (s[i] != c) printf("%c", s[i]); printf("\n"); getchar(); } return 0; }
#include <cstdio> #include <cstring> int main() { char s[210]; while (gets(s) != NULL) { //可能有空格 for (int i = strlen(s) - 1; i >= 0; i--) printf("%c", s[i]); printf("\n"); } return 0; }
这里我没有直接用字符串函数strlen,不过我以为strlen可能就是这么写的。
#include <cstdio> int main() { char s[100], r[100]; int m; scanf("%d", &m); while (m--) { scanf("%s%s", s, r); int slen = 0, rlen = 0; for (slen = 0; s[slen]; slen++); for (rlen = 0; r[rlen]; rlen++); if (slen == rlen) { printf("%s is equal long to %s\n", s, r); } else if (slen > rlen) { printf("%s is longer than %s\n", s, r); } else { printf("%s is shorter than %s\n", s, r); } } }
题目描述:请输入字符串,最多输入4 个字符串,要求后输入的字符串排在前面,例如:
输入:EricZ 输出:1=EricZ 输入:David 输出:1=David 2=EricZ 输入:Peter 输出:1=Peter 2=David 3=EricZ 输入:Alan 输出:1=Alan 2=Peter 3=David 4=EricZ 输入:Jane 输出:1=Jane 2=Alan 3=Peter 4=David
5 EricZ David Peter Alan Jane
1=EricZ 1=David 2=EricZ 1=Peter 2=David 3=EricZ 1=Alan 2=Peter 3=David 4=EricZ 1=Jane 2=Alan 3=Peter 4=David
这题麻烦在于没怎么作过这种类型,至关于实现了一个有大小限制的字符串容器,新进入的字符串会把旧的字符串挤下来,甚至挤出去。
#include <cstdio> #include <cstring> int main() { int m; scanf("%d", &m); char s[5][35]; //使用1-4行 for (int i = 1; i <= m; i++) { int j, w = i >= 1 && i <= 4 ? i : 4; //得到字符串数目 for (j = w; j > 1; j--) { //将旧的字符串移到下一个位置 strcpy(s[j], s[j - 1]); } scanf("%s", s[1]); //永远在第一个位置存入新字符串 for (int k = 1; k <= w; k++) { //按格式打印所有已存入的字符串 if (k < w) printf("%d=%s ", k, s[k]); else printf("%d=%s\n", k, s[k]); } } return 0; }
一行字符串,长度不超过255。我的以为,我这种判断回文串的方法最简单最好写。
#include <cstdio> #include <cstring> int main() { char s[260]; while (gets(s) != NULL) { int left = 0, right = strlen(s) - 1, flag = 1; for (int i = left, j = right; i < j; i++, j--) { //双指针滑动 if (s[i] != s[j]) { printf("NO\n"); flag = 0; break; } } if (flag) printf("YES\n"); } return 0; }
对输入的n个数进行从小到大的排序并输出。
先本身实现一个插入排序的程序。
#include <cstdio> int main() { int n, a[120]; while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } //插入排序 for (int i = 1; i < n; i++) { int temp = a[i], j; for (j = i; j > 0 && temp < a[j - 1]; j--) a[j] = a[j - 1]; a[j] = temp; } //输出 for (int i = 0; i < n; i++) { printf("%d", a[i]); if (i < n - 1) printf(" "); else printf("\n"); } } }
再使用C++的库函数sort()直接排序。其使用格式sort(要排序的数组, 数组元素末项的下一项, 排序函数)
。
#include <cstdio> #include <algorithm> using namespace std; int main() { int n, a[120]; while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } //排序 sort(a, a + n); //输出 for (int i = 0; i < n; i++) { printf("%d", a[i]); if (i < n - 1) printf(" "); else printf("\n"); } } }
#include <cstdio> #include <algorithm> using namespace std; int main() { int n, a[1010]; while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } if (n == 1) { //只有1个元素 printf("%d\n", a[0]); printf("-1\n"); continue; } sort(a, a + n); printf("%d\n", a[n - 1]); for (int i = 0; i < n - 1; i++) { printf("%d", a[i]); if (i < n - 2) printf(" "); else printf("\n"); } } return 0; }
题目描述
Excel能够对一组纪录按任意指定列排序。现请你编写程序实现相似功能。
对每一个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3 时,按成绩的非递减排序。当若干学生具备相同姓名或者相同成绩时,则按他们的学号递增排序。
4 1 000001 Zhao 75 000004 Qian 88 000003 Li 64 000002 Sun 90 4 2 000005 Zhao 95 000011 Zhao 75 000007 Qian 68 000006 Sun 85 4 3 000002 Qian 88 000015 Li 95 000012 Zhao 70 000009 Sun 95 0 3
Case 1: 000001 Zhao 75 000002 Sun 90 000003 Li 64 000004 Qian 88 Case 2: 000007 Qian 68 000006 Sun 85 000005 Zhao 95 000011 Zhao 75 Case 3: 000012 Zhao 70 000002 Qian 88 000009 Sun 95 000015 Li 95
这道问题的题目描述中,2和3的排序都要二级排序。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct student { int id; // 6 char name[10]; int score; } excelBook[100050]; bool cmp1(struct student a, struct student b) { return a.id < b.id; //按学号递增排序 } bool cmp2(struct student a, struct student b) { //按姓名的非递减字典序排序 if (strcmp(a.name, b.name)) return strcmp(a.name, b.name) < 0; else return a.id < b.id; } bool cmp3(struct student a, struct student b) { if (a.score != b.score) return a.score < b.score; //按成绩的递增排序 else return a.id < b.id; } int main() { int N, C, caseCount = 0; while (scanf("%d%d", &N, &C), N) { for (int i = 0; i < N; i++) { scanf("%d%s%d", &excelBook[i].id, excelBook[i].name, &excelBook[i].score); } switch (C) { case 1: //当 C=1 时,按学号递增排序 sort(excelBook, excelBook + N, cmp1); break; case 2: //当 C=2时,按姓名的非递减字典序排序 sort(excelBook, excelBook + N, cmp2); break; case 3: //当 C=3 时,按成绩的非递减排序, 当若干学生具备相同姓名或者相同成绩时, //则按他们的学号递增排序 sort(excelBook, excelBook + N, cmp3); break; } //打印输出 printf("Case %d:\n", ++caseCount); for (int i = 0; i < N; i++) { printf("%06d %s %d\n", excelBook[i].id, excelBook[i].name, excelBook[i].score); } } return 0; }
注意输入的字符串中可能有空格。所以要使用gets输入字符串,并且按字符从小到大排序,空格排在最前。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int main() { char s[210]; while (gets(s)) { int len = strlen(s); sort(s, s + len); puts(s); } return 0; }
求矩阵每一行、每一列、主次对角线和,并排序。即便只有一个元素,也要输出4个和。
#include <cstdio> #include <algorithm> using namespace std; bool cmp(int a, int b) { return a > b; } int matrix[12][12]; int r[30]; int main() { int m; while (scanf("%d", &m) != EOF) { int len = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { scanf("%d", &matrix[i][j]); } } //每一行与列求和 for (int i = 0; i < m; i++) { int Rsum = 0, Csum = 0; for (int j = 0; j < m; j++) { Rsum += matrix[i][j]; Csum += matrix[j][i]; } r[len++] = Rsum; r[len++] = Csum; } //主次对角线求和 int LDsum = 0, RDsum = 0; for (int i = 0; i < m; i++) { LDsum += matrix[i][i]; RDsum += matrix[i][m - i - 1]; } r[len++] = LDsum; r[len++] = RDsum; sort(r, r + len, cmp); for (int i = 0; i < len - 1; i++) { printf("%d ", r[i]); } printf("%d\n", r[len - 1]); } return 0; }
#include <cstdio> #include <algorithm> using namespace std; struct rat { int weight; char color[15]; } mice[120]; bool cmp(struct rat a, struct rat b) { return a.weight > b.weight; //按重量从大到小, 重量各不相同 } int main() { int N; while (scanf("%d", &N) != EOF) { for (int i = 0; i < N; i++) { scanf("%d%s", &mice[i].weight, mice[i].color); } sort(mice, mice + N, cmp); for (int i = 0; i < N; i++) { puts(mice[i].color); //输出小白鼠的颜色 } } }
#include <cstdio> #include <algorithm> using namespace std; int a[10010]; int main() { int N; while (scanf("%d", &N), N) { for (int i = 0; i < N; i++) { scanf("%d", &a[i]); } sort(a, a + N); int mid = (0 + N - 1) / 2; if (N % 2) { printf("%d\n", a[mid]); } else { //求最中间两个数的平均数,向下取整便可 printf("%d\n", (a[mid] + a[mid + 1]) / 2); } } return 0; }
#include <iostream> #include <algorithm> using namespace std; bool cmp(int a, int b) { return a > b; } int main() { int a[10], odd[10], even[10]; while(cin>>a[0]>>a[1]>>a[2]>>a[3]>>a[4] >>a[5]>>a[6]>>a[7]>>a[8]>>a[9]) { int len1 = 0, len2 = 0; for (int i = 0; i < 10; i++) { a[i] % 2 ? odd[len1++] = a[i] : even[len2++] = a[i]; } sort(odd, odd + len1, cmp); sort(even, even + len2); //输出其中的奇数,并按从大到小排列; 输出其中的偶数,并按从小到大排列 for (int i = 0; i < len1; i++) a[i] = odd[i]; for (int j = len1; j < 10; j++) a[j] = even[j - len1]; for (int k = 0; k < 10; k++) { cout << a[k]; if (k < 9) cout << " "; else cout << endl; } } return 0; }
这题比较简单,计算好合格的分数后按题目要求排序便可。
#include <cstdio> #include <cstring> #include <algorithm> struct student { char id[25]; int m, TotalScores; } stu[1050]; using namespace std; bool cmp(struct student a, struct student b) { if (a.TotalScores != b.TotalScores) return a.TotalScores > b.TotalScores; else return strcmp(a.id, b.id) < 0; } int main() { int N, M, G; while (scanf("%d", &N), N) { scanf("%d%d", &M, &G); //记录考题数M、分数线G int exerScores[M + 1], cases = 0; //经过人数 for (int i = 1; i <= M; i++) scanf("%d", &exerScores[i]); //记录每道题的分数 for (int i = 0; i < N; i++) { scanf("%s%d", stu[i].id, &stu[i].m); //记录考号和作出题数 int sum = 0, t; for (int j = 0; j < stu[i].m; j++) { scanf("%d", &t); sum += exerScores[t]; //求出考生总分 } if (sum >= G) { cases++; //超出分数线 stu[i].TotalScores = sum; //记录合格的分数 } } sort(stu, stu + cases, cmp); printf("%d\n", cases); for (int i = 0; i < cases; i++) { printf("%s %d\n", stu[i].id, stu[i].TotalScores); } } return 0; }
http://codeup.cn/contest.php?cid=100000582
在哈希这一块经常使用的问题包括:判断<=105个正整数中某m个正整数是否出现过、出现了多少次——声明bool/int hashTable[maxn] = {false}/{0}
。其作法本质是直接将输入的整数做为数组的下标来对这个数的性质进行统计,即hash(key)=key
直接定址,是最多见也最实用的散列应用。复杂一点还有二次映射。把这两个思想掌握了就差很少了。
本题中也是使用了这种作法,直接将输入的数做为数组的下标。分别有两个数组,记录记录1-N每一个人喜欢看的书号的数组person,记录1-M每本书的喜欢人数的数组note。若是要经过某我的的编号查询到有多少人和这我的喜欢同一本书的写法是:note[person[i]]
。实质是在人与书号间造成了一种单射。接下来就简单了。
#include <cstdio> int main() { int N, M; while (scanf("%d%d", &N, &M) != EOF) { int person[N + 1], note[M + 1] = {0}, tmp; for (int i = 1; i <= N; i++) { scanf("%d", &tmp); person[i] = tmp; //记录1-N每一个人喜欢看的书号 note[tmp]++; //记录每本书的喜欢人数 } for (int i = 1; i <= N; i++) { if (note[person[i]] > 1) printf("%d\n", note[person[i]] - 1); else printf("BeiJu\n"); } } return 0; }
题目描述:先输入一组数,而后输入其分组,按照分组统计出现次数并输出,参见样例。
1 7 3 2 3 8 8 2 3 1 2 3 2 1 3 1
1={2=0,3=2,8=1} 2={2=1,3=0,8=1} 3={2=1,3=1,8=0
解析:这一道题目能够说是集整数哈希思想于大成,值得仔细分析。
整数做为数组的下标
超过数组下标范围,理论上来讲,对于这种题目,以空间换时间,要求数据应该不超过106。所以,统计输入的数据和组别是否已经出现,能够开hashTable[100100]这样大。思路:
a[i][j]为第i组的j数出现的次数
。#include <cstdio> #include <algorithm> using namespace std; int main() { int m; scanf("%d", &m); while (m--) { int n, maxCol = 0, data[110], group[110]; //分别记录输入的数据和分组 scanf("%d", &n); //nums记录输入的数据去重后的数据 int nums[120], len1 = 0; //使用哈希表对data进行存在标识, 以便去重 bool hashTable1[100100] = {false}; for (int i = 0; i < n; i++) { scanf("%d", &data[i]); //边录入边去重 if (!hashTable1[data[i]]) { //若是这个数据还没有被记录 nums[len1++] = data[i]; hashTable1[data[i]] = true; } //获得最大的数, 方便答案直接映射而不溢出 if (maxCol < data[i]) maxCol = data[i]; } sort(nums, nums + len1); //数据从小到大存放在nums中, 无重复 //g记录输入的组别去重后的数据 int g[120], len2 = 0; //使用哈希表对group进行存在标识, 以便去重 bool hashTable2[100100] = {false}; /*二维答案表,元素ans[g[i]][nums[j]]表示g[i]组中对应的nums[j]出现的次数 ans[i][j], i为分组, j为数, a[i][j]为第i组的j数出现的次数 */ int ans[n + 10][maxCol + 10] = {0}; for (int i = 0; i < n; i++) { scanf("%d", &group[i]); ans[group[i]][data[i]]++; if (!hashTable2[group[i]]) { //若是这个组别还没有被记录 g[len2++] = group[i]; hashTable2[group[i]] = true; } } sort(g, g + len2); //组别从小到大存放在g中, 无重复 //输出结果 for (int i = 0; i < len2; i++) { printf("%d={", g[i]); for (int j = 0; j < len1; j++) { printf("%d=%d", nums[j], ans[g[i]][nums[j]]); if (j < len1 - 1) printf(","); else printf("}\n"); } } } return 0; }
这道题的难点在于找出第一个独特的数,其实只要按照输入的数组顺序,在记录次数的哈希表中查找只出现一次的数,发现了一个就结束查找并输出,直到最后也没找到就是没有。
#include <cstdio> const int maxn = 10500; int main() { int N; while (scanf("%d", &N) != EOF) { int hashTable[maxn] = {0}, tmp[N]; for (int i = 0; i < N; i++) { scanf("%d", &tmp[i]); hashTable[tmp[i]]++; } int win = 0; for (int i = 0; i < N; i++) { if (hashTable[tmp[i]] == 1) { printf("%d\n", tmp[i]); win = 1; break; } } if (!win) printf("None\n"); } }
all the characters are visible ASCII codes and white space
。输入的字符包括字母数字和各类符号这些可见ascll字符,还有空格,所以须要能容纳整个ascll码的哈希表。这题虽然是字符串,但实际上仍是整数哈希。
#include <cstdio> int main() { char s1[10100], s2[10100]; while (gets(s1) != NULL) { bool hashTable[130] = {false}; gets(s2); for (int i = 0; s2[i]; i++) { hashTable[s2[i]] = true; //将字符相应ascii码位置的哈希表设为true } for (int i = 0; s1[i]; i++) { if (!hashTable[s1[i]]) //若是字符没有出如今s2中 printf("%c", s1[i]); } printf("\n"); } }
http://codeup.cn/contest.php?cid=100000583
不少数据结构自己也是递归定义的。
题目描述
名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0)。
妈妈告诉名名天天能够吃一块或者两块巧克力。
若是N=1,则名名第1天就吃掉它,共有1种方案;
若是N=2,则名名能够第1天吃1块,第2天吃1块,也能够第1天吃2块,共有2种方案;
若是N=3,则名名第1天能够吃1块,剩2块,也能够第1天吃2块剩1块,因此名名共有2+1=3种方案;
若是N=4,则名名能够第1天吃1块,剩3块,也能够第1天吃2块,剩2块,共有3+2=5种方案。
假设名名天天都吃巧克力,问名名共有多少种不一样的吃完巧克力的方案。
1 2 4
1 2 5
每次吃的时候,名名能够吃一块巧克力,或者吃两块巧克力,也就是说,每次吃的时候,有两种吃法。
这个题目能够有多种解法,不过大致是分治的思路(循环实现)。将一个大的问题F(N)
分红多个小的性质相同的问题F(N-1)和F(N-2)
,运用递归或非递归求解这些子问题,而后合并起来。动态规划的实际代码以下,就是变形的斐波拉契数列。
#include <cstdio> int a[30] = {0, 1, 2}; int main() { int N; for (int i = 3; i <= 20; i++) { a[i] = a[i - 1] + a[i - 2]; } while (scanf("%d", &N) != EOF) { printf("%d\n", a[N]); } return 0; }
题目描述:编写一个求斐波那契数列的递归函数,输入n 值,使用该递归函数,输出以下图形(参见样例)。
1 6
0 0 1 1 0 1 1 2 3 0 1 1 2 3 5 8 0 1 1 2 3 5 8 13 21 0 1 1 2 3 5 8 13 21 34 55
出于对递归求解斐波那契数列(这绝对不是分治!)的厌恶,我仍是选择了循环。
#include <cstdio> int main() { int fib[25] = {0, 1, 1}; //f(0) = 0 for (int i = 3; i <= 20; i++) fib[i] = fib[i - 1] + fib[i - 2]; int m, n; scanf("%d", &m); while (m--) { scanf("%d", &n); for (int i = 1; i <= n; i++) { //打印n层 int spaceNum = (n - i) * 2; //打印空格 for (int l = 0; l < spaceNum; l++) { printf(" "); } for (int j = 0; j < 2 * i - 1; j++) { printf("%d", fib[j]); if (j < 2 * i - 2) printf(" "); else printf("\n"); } } } return 0; }
题目描述
有一个神奇的口袋,总的容积是40,用这个口袋能够变出一些物品,这些物品的整体积必须是40。John如今有n个想要获得的物品,每一个物品的体积分别是a1,a2……an。John能够从这些物品中选择一些,若是选出的物体的整体积是40,那么利用这个神奇的口袋,John就能够获得这些物品。如今的问题是,John有多少种不一样的选择物品的方式。
2 12 28 3 21 10 5
1 0
在我刷LeetCode的数组-回溯算法中的子集问题与这个问题十分类似,参照一下,都是对一棵树的深度遍历。递归边界是40,递归式(缩小问题范围)是经过移动数组指针的方式进行的。https://blog.csdn.net/myRealization/article/details/97446896
#include <cstdio> const int maxn = 25, Capacity = 40; int cnt; //合法方案的数目 /* 至关于求出stuffs[]集合的真子集, 并判断总重量是否合适 */ void MagicalDFS(int weight, int stuffs[], int pos) { if (weight == Capacity) { //进入这里的就是合法方案 cnt++; //方案+1 return; } for (int i = pos; stuffs[i] != 0; i++) { //printf("weight = %d + %d\n", weight, stuffs[i]); weight += stuffs[i]; if (weight <= Capacity) { MagicalDFS(weight, stuffs, i + 1); //深刻遍历下一层 } weight -= stuffs[i]; //这一条路径遍历到底部, 从下一层返回到本层的状态 } } int main() { int n; while (scanf("%d", &n) != EOF) { int a[maxn] = {0}; for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } cnt = 0; MagicalDFS(0, a, 0); printf("%d\n", cnt); } }
题目描述:会下国际象棋的人都很清楚:皇后能够在横、竖、斜线上不限步数地吃掉其余棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个知足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2…b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不一样的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y以前,当且仅当将x视为整数时比y小。
3 6 4 25
25713864 17582463 36824175
在我刷LeetCode的回溯算法中的N皇后问题与这个问题同出一源,参照一下,思路基本同样。https://blog.csdn.net/myRealization/article/details/97446896
#include <cstdio> #include <algorithm> using namespace std; //n为皇后的个数, 哈希表用来记录整数x是否已经在col中, col为不一样行皇后所在列的一个排列 int n, hashTable[10] = {false}, col[10] = {0}, QueenStringList[100], p = 1; //皇后串的结果表 void QueenDFS(int CurRow) { if (CurRow == n + 1) { for (int i = 1; i <= 8; i++) QueenStringList[p] = QueenStringList[p] * 10 + col[i]; p++; return; } for (int x = 1; x <= 8; x++) { //第x列 if (hashTable[x] == false) { //第x列尚未皇后 bool flag = true; //flag为true表示和以前的皇后不会冲突 for (int pre = 1; pre < CurRow; pre++) { if (abs(CurRow - pre) == abs(x - col[pre])) { flag = false; //同以前的皇后在一条对角线上冲突 break; } } if (flag) { //若是能够摆放在这一列 hashTable[x] = true; //这一列已经被占用 col[CurRow] = x; //令当前行的列号为x QueenDFS(CurRow + 1); //递归处理第curRow+1行的皇后该摆放在哪一列 hashTable[x] = false; //递归完毕, 不管是否此次递归抵达边界, 都还原其为未占用 } } } } int main() { int m; scanf("%d", &m); n = 8; //启动为8皇后 QueenDFS(1); while (m--) { int b; scanf("%d", &b); printf("%d\n", QueenStringList[b]); } return 0; }
http://codeup.cn/contest.php?cid=100000584
题目描述
暑假到了,小明终于能够开心的看电视了。可是小明喜欢的节目太多了,他但愿尽可能多的看到完整的节目。
如今他把他喜欢的电视节目的转播时间表给你,你能帮他合理安排吗?
12 1 3 3 4 0 7 3 8 15 19 15 20 10 15 8 18 6 12 5 10 4 14 2 9 0
5
颇有意思的区间贪心问题,这里老是先选择左端点最大的区间,老是先选择右端点最小的区间也是可行的。
与之相似的是区间选点问题,给定N个闭区间[x, y],求最少须要肯定多少个点才能保证每一个闭区间中都至少存在一个点
。例如对闭区间[1, 4]、[2, 6]、[5, 7]
来讲须要两个点如三、5,才能确保每一个闭区间内都至少有一个点。代码写法也是相似的。
#include <cstdio> #include <algorithm> using namespace std; struct Inteval { int left, right; //左右区间端点表示 }; bool cmp(struct Inteval a, struct Inteval b) { if (a.left != b.left) return a.left > b.left; // 按区间左端点大小从大到小排序 else return a.right < b.right; //左端点相同, 按右端点大小从小到大排序 } int main() { int N; while (scanf("%d", &N), N) { struct Inteval a[N]; for (int i = 0; i < N; i++) { scanf("%d%d", &a[i].left, &a[i].right); } sort(a, a + N, cmp); //把区间排序 //ans为不相交区间个数, lastLeft为上一个被选中区间的左端点 int ans = 1, lastLeft = a[0].left; for (int i = 1; i < N; i++) { if (a[i].right <= lastLeft) { //若是该区间右端点在lastLeft左边 ans++; //不相交区间个数加1 lastLeft = a[i].left; //以a[i]做为新选中的区间 } } printf("%d\n", ans); } return 0; }
#include <cstdio> #include <algorithm> using namespace std; int main() { int N; while (scanf("%d", &N), N) { //一个正整数n表示整个行程的千米数 if (N <= 4) { //不足4千米确定10元 printf("%d\n", 10); continue; } else if (N <= 8) { //4-8千米第二段直接计算 printf("%d\n", 10 + (N - 4) * 2); //每千米最小单价 continue; } else { //超过8千米优先走8千米的第二段与第一段的混合 int part = N / 8, last = N % 8; if (last == 0) printf("%d\n", part * 18); else if (last <= 4) { //超过8千米最后的部分在4之内走2.4元那段 printf("%.1f\n", part * 18 + last * 2.4); } else { //在4-8的话还走第一二段 printf("%d\n", part * 18 + 10 + (last - 4) * 2); } } } return 0; }
提示:该题目所要解决的问题是:给定若干加油站信息,问可否驾驶汽车行驶必定的距离。若是可以行驶彻底程,则计算最小花费。若不能行驶彻底程,则最远可以行驶多长距离。
拿到这一题,首先判断汽车是否可以行驶到终点。什么状况下汽车没法行驶到终点呢?两种状况:起点根本就没有加油站,汽车没法启动;或者中途两个加油站之间的距离大于加满油后汽车可以行驶的最大距离
。前者汽车行驶的最大距离为0.00,然后者最大距离为当前加油站的距离加上在这个加油站加满油后可以行驶的最大距离。在这里,须要将加油站按到杭州的距离从小到大排序。
接下来在可以行驶到终点的状况下计算最小花费。咱们首先从路程来考虑,若是在路上,咱们可以使用最便宜的汽油,固然就在那个加油站加油了。因此从起点开始遍历每一个加油站。假设遍历到了第i个加油站,咱们如今来判断在加油站i应该加多少油。
单点测试,有难度,并且我不太明白 。
#include <cstdio> #include <algorithm> using namespace std; typedef struct gasStation { double p, d, s; //p: 价格,d:据出发点距离,s:离上个站点的间距 } gs; bool cmp(gs a, gs b) { return a.d < b.d; } int main() { double C, D, Davg; int n; //从杭州到目的地的加油站数目 while (scanf("%lf%lf%lf%d", &C, &D, &Davg, &n) != EOF) { gs gstat[n + 1]; double maxl = C * Davg; //满油后最大行驶距离 for (int i = 0; i < n; i++) { scanf("%lf%lf", &gstat[i].p, &gstat[i].d); } gstat[n].p = 0; //目的地 gstat[n].d = D; sort(gstat, gstat + n + 1, cmp); for (int i = 1; i <= n; i++) { gstat[i].s = gstat[i].d - gstat[i - 1].d; } int flag = 1; /* 若是第一个加油站不在杭州, 无法加油 */ if (gstat[0].d > 0) { flag = 0; printf("The maximum travel distance = 0.00\n"); } else { for (int i = 1; i <= n; i++) { if (gstat[i].s > maxl) { //有站点不可达 flag = 0; printf("The maximum travel distance = %.2f\n", gstat[i - 1].d + maxl); break; } } } double cost = 0, nowTank = 0; int nowSta = 0, signal = 1; if (flag) { for (int i = 0; i < n; i++) { if (i != nowSta) continue; for (int j = i + 1; j <= n && (gstat[j].d - gstat[i].d) <= maxl; j++) { if (gstat[j].p < gstat[nowSta].p) { if (nowTank < (gstat[j].d - gstat[nowSta].d) / Davg) { cost += gstat[nowSta].p * ((gstat[j].d - gstat[nowSta].d) / Davg - nowTank); nowTank = 0; } else nowTank -= (gstat[j].d - gstat[nowSta].d) / Davg; nowSta = j; signal = 1; break; } else signal = 0; } if (!signal) { cost += gstat[i].p * (C - nowTank); nowTank = C - (gstat[i + 1].s / Davg); nowSta++; } } printf("%.2f\n", cost); } } return 0; }
先用更长的砖头修墙。
#include <cstdio> #include <algorithm> using namespace std; bool cmp(int a, int b) {return a > b;} int main() { int L, N; while (scanf("%d%d", &L, &N) != EOF) { int a[N + 1], sum = 0; for (int i = 0; i < N; i++) { scanf("%d", &a[i]); sum += a[i]; } if (sum < L) printf("impossible\n"); else { sort(a, a + N, cmp); //砖按长度从长到短排序 int cnt = 0; for (int i = 0; i < N; i++) { if (L > a[i]) { L -= a[i]; cnt++; } else { L = 0; cnt++; break; } } printf("%d\n", cnt); } } return 0; }
这道题简单,可以多换的房间就多换。
#include <cstdio> #include <algorithm> using namespace std; struct room { double J, F; //J: javabeans F: cat food double rate; // J/F }; bool cmp(struct room a, struct room b) { return a.rate > b.rate; } int main() { int m, n; while (scanf("%d%d", &m, &n), m != -1 && n != -1) { struct room house[n + 1]; for (int i = 0; i < n; i++) { scanf("%lf%lf", &house[i].J, &house[i].F); house[i].rate = house[i].J / house[i].F; } sort(house, house + n, cmp); double javabeans = 0.0; /* 从猫食物换取Javabeans的兑换比率最高的换起 */ for (int i = 0; i < n; i++) { /* 若是老鼠的猫食物够多, 能够将这个房间中的java豆所有换完 */ if (m >= house[i].F) { javabeans += house[i].J; m -= house[i].F; } else { /* 若是猫食物不够多, 能换多少就换多少 */ javabeans += house[i].rate * m; m = 0; break; } } printf("%.3f\n", javabeans); } return 0; }
溶质体积/溶液体积=浓度
。从浓度小的溶液开始配。
#include <cstdio> #include <algorithm> using namespace std; bool cmp(int a, int b) {return a > b;} int main() { int C, N; while (scanf("%d", &C) != EOF) { while (C--) { int n, V, W; scanf("%d%d%d", &n, &V, &W); double p[n + 1]; for (int i = 0; i < n; i++) scanf("%lf", &p[i]); sort(p, p + n); double solP = 0.0; int solV = 0; for (int i = 0; i < n; i++) { if ((p[i] * V + solP * solV) / (V + solV) <= W) { solP = (p[i] * V + solP * solV) / (V + solV); solV += V; } else break; } if (!solV) printf("0 0.00\n"); else printf("%d %.2lf\n", solV, solP / 100); } } return 0; }
题目描述:小智去超市买东西,买了不超过一百块的东西。收银员想尽可能用少的纸币来找钱。
纸币面额分为50 20 10 5 1 五种。请在知道要找多少钱n给小明的状况下,输出纸币数量最少的方案。 1<=n<=99。
25 32
20*1+5*1 20*1+10*1+1*2
#include <cstdio> int main() { int n; while (scanf("%d", &n) != EOF) { int hashTable[51] = {0}, money[5] = {50, 20, 10, 5, 1}, cnt = 0; for (int i = 0; i < 5 && n; i++) { while (n >= money[i]) { //优先减小最大额度的纸币 n -= money[i]; hashTable[money[i]]++; //数该额度的纸币的张数 cnt++; } } for (int i = 0; i < 5; i++) { if (hashTable[money[i]]) { printf("%d*%d", money[i], hashTable[money[i]]); cnt -= hashTable[money[i]]; if (cnt > 0) printf("+"); else printf("\n"); } } } return 0; }
http://codeup.cn/contest.php?cid=100000585
#include <cstdio> int findx(int a[], int n, int x) { for (int i = 0; i < n; i++) if (a[i] == x) return i; return -1; } int main() { int n; while (scanf("%d", &n) != EOF) { int a[n]; for (int i = 0; i < n; i++) scanf("%d", &a[i]); int x; scanf("%d", &x); printf("%d\n", findx(a, n, x)); } return 0; }
必须得说这个和二分没有关系。
#include <cstdio> int main() { int n; while (scanf("%d", &n) != EOF) { while (n--) { int k; scanf("%d", &k); int a[k], index[k], cnt = 0; for (int i = 0; i < k; i++) { scanf("%d", &a[i]); } if (a[0] != a[1]) index[cnt++] = 0; for (int i = 1; i < k - 1; i++) { if ( (a[i] > a[i - 1] && a[i] > a[i + 1]) || (a[i] < a[i - 1] && a[i] < a[i + 1]) ) index[cnt++] = i; } if (a[k - 1] != a[k - 2]) index[cnt++] = k - 1; for (int i = 0; i < cnt; i++) { printf("%d", index[i]); if (i < cnt - 1) printf(" "); else printf("\n"); } } } return 0; }
#include <cstdio> int main() { int n; while (scanf("%d", &n) != EOF) { int a[n]; for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } int m; scanf("%d", &m); int t; while (m--) { scanf("%d", &t); int i; for (i = 0; i < n; i++) { if (a[i] == t) { printf("YES\n"); break; } } if (i == n) printf("NO\n"); } } return 0; }
题目不可用?!
http://codeup.cn/contest.php?cid=100000566
双指针的经典问题能够看个人LeetCode刷题记录中的283题-移动零。https://blog.csdn.net/myRealization/article/details/97446896
书上的二路归并排序写得并很差,主要是每一次都申请一个临时数组太浪费了。并且这个题目测试用例有问题,个人代码线下能够正确运行,线上都是运行错误0……
啊,找到缘由了,这个题目没有给出输出格式,且只有一个测试用例,把全代码的main函数改为下面的结构和输出方式就能够了。所以,程序正确的话显示为运行错误80。
int main() { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); mergeSort(a, n); for (int i = 0; i < n; i++) printf("%d\n", a[i]); return 0; }
#include <cstdio> #include <cstring> #include <cstdlib> /* 将数组A的[L1, R1]与[L2, R2]区间归并为有序区间到tmpArray, 再拷贝回A */ void merge(int A[], int tmpArray[], int L1, int R1, int L2, int R2) { int i = L1, j = L2, index = 0; while (i <= R1 && j <= R2) { if (A[i] <= A[j]) tmpArray[index++] = A[i++]; else tmpArray[index++] = A[j++]; } while (i <= R1) tmpArray[index++] = A[i++]; //将[L1, R1]剩余元素加入序列 while (j <= R2) tmpArray[index++] = A[j++]; //将[L2, R2]剩余元素加入序列 for (i = 0; i < index; i++) A[L1 + i] = tmpArray[i]; //将合并后的序列赋值回A } void MSort(int A[], int tmpArray[], int left, int right) { if (left < right) { int mid = (left + right) / 2; MSort(A, tmpArray, left, mid); MSort(A, tmpArray, mid + 1, right); merge(A, tmpArray, left, mid, mid + 1, right); } } void mergeSort(int A[], int N) { int *tmpArray = (int *)malloc(N * sizeof(int)); MSort(A, tmpArray, 0, N - 1); free(tmpArray); } int a[100100]; int main() { int n; while (scanf("%d", &n) != EOF) { memset(a, 0, sizeof(a)); for (int i = 0; i < n; i++) scanf("%d", &a[i]); mergeSort(a, n); for (int i = 0; i < n; i++) { if (i > 0) printf(" "); printf("%d", a[i]); } printf("\n"); } return 0; }
题目描述:归并排序是一个时间复杂度为O(nlogn)的算法,对于大量数据远远优于冒泡排序与插入排序。这是一道排序练习题,数据量较大,请使用归并排序完成。
又写了一遍递归归并排序,这才是上一题的题目吧。
#include <cstdio> #include <cstring> #include <cstdlib> void merge(int a[], int tmpArray[], int L1, int R1, int L2, int R2) { int i = L1, j = L2, index = 0; while (i <= R1 && j <= R2) { if (a[i] <= a[j]) tmpArray[index++] = a[i++]; else tmpArray[index++] = a[j++]; } while (i <= R1) tmpArray[index++] = a[i++]; while (j <= R2) tmpArray[index++] = a[j++]; for (int i = 0; i < index; i++) a[L1 + i] = tmpArray[i]; } void msort(int a[], int tmpArray[], int left, int right) { int i = left, j = right, mid; if (left < right) { mid = (left + right) / 2; msort(a, tmpArray, left, mid); msort(a, tmpArray, mid + 1, right); merge(a, tmpArray, left, mid, mid + 1, right); } } void mergeSort(int a[], int n) { int* tmpArray = (int *)malloc(sizeof(int) * n); msort(a, tmpArray, 0, n - 1); free(tmpArray); } int a[100010]; int main() { int n, m; scanf("%d", &n); while (n--) { memset(a, 0, sizeof(a)); scanf("%d", &m); for (int i = 0; i < m; i++) scanf("%d", &a[i]); mergeSort(a, m); for (int i = 0; i < m; i++) printf("%d\n", a[i]); } return 0; }
#include <cstdio> int partition(int a[], int left, int right) { int temp = a[left]; //将a[left]存进临时变量 while (left < right) { //只要二者不相遇 while (left < right && a[right] > temp) right--; //持续左移 a[left] = a[right]; //将a[right]移至a[left] while (left < right && a[left] <= temp) left++; a[right] = a[left]; //将a[left]移至a[right] } a[left] = temp; //将temp移至left与right相遇的地方 return left; //返回枢纽元的位置即相遇的下标(分割点) } void qsort(int a[], int left, int right) { if (left < right) { //当前区间的长度超过1 //将[left, right]按照a[left]一分为2 int pos = partition(a, left, right); qsort(a, left, pos - 1); //对左区间递归 qsort(a, pos + 1, right); //对右区间递归 } } void quickSort(int a[], int n) { qsort(a, 0, n - 1); } int a[6000]; int main() { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); quickSort(a, n); for (int i = 0; i < n; i++) printf("%d\n", a[i]); return 0; }
这两个题目都是写二分递归快排的,因此问题C我写的是始终采起第一个元素做为枢纽元的二分递归快排,
而这一题我写的是随机选择快排。
#include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <algorithm> using namespace std; //选择随机主元, 对区间[left, right]进行划分 int randomPartition(int a[], int left, int right) { //生成[left, right]区间的随机数pos int pos = (int)(round(1.0 * rand() / RAND_MAX * (right - left) + left)); swap(a[pos], a[left]); //交换a[pos]和a[left] int temp = a[left]; while (left < right) { while (left < right && a[right] > temp) right--; a[left] = a[right]; while (left < right && a[left] <= temp) left++; a[right] = a[left]; } a[left] = temp; return left; } void qsort(int a[], int left, int right) { if (left < right) { int pos = randomPartition(a, left, right); qsort(a, left, pos - 1); qsort(a, pos + 1, right); } } void quickSort(int a[], int n) { qsort(a, 0, n - 1); } int a[100100]; int main() { srand((unsigned)time(NULL)); int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); quickSort(a, n); for (int i = 0; i < n; i++) printf("%d\n", a[i]); return 0; }
http://codeup.cn/contest.php?cid=100000587
#include <cstdio> #include <algorithm> using namespace std; bool cmp(int a, int b) { return a > b; //从大到小排序 } int main() { int m, n; scanf("%d%d", &m, &n); int a[m]; for (int i = 0; i < m; i++) scanf("%d", &a[i]); sort(a, a + m, cmp); printf("%d", a[n-1]); return 0; }
实际上这道题是考验写随机选择算法的,代码以下,个人版本为randSelect2,增强版的相似递归二分查找。书上的讲解讲错了,代码实际上求的是第k小的数,第k大的数就是第(n-k+1)小的数,输入参数改一下就好了。
#include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <algorithm> using namespace std; //选择随机主元, 对区间[left, right]进行划分 int randPartition(int a[], int left, int right) { //生成[left, right]区间的随机数pos int pos = (int)(round(1.0 * rand() / RAND_MAX * (right - left) + left)); swap(a[pos], a[left]); //交换a[pos]和a[left] int temp = a[left]; while (left < right) { while (left < right && a[right] > temp) right--; a[left] = a[right]; while (left < right && a[left] <= temp) left++; a[right] = a[left]; } a[left] = temp; return left; } int randSelect(int a[], int left, int right, int K) { if (left == right) return a[left]; int pos = randPartition(a, left, right); //划分后主元位置为pos int M = pos - left + 1; //a[p]是a[left, right]中的第M小 if (K == M) return a[pos]; //找到第K小的数 if (K < M) return randSelect(a, left, pos - 1, K); //向左边找第K小的数 else return randSelect(a, pos + 1, right, K - M); //向右边找第K-M小 } int randSelect2(int a[], int left, int right, int K) { while (left <= right) { int pos = randPartition(a, left, right); //划分后主元位置为pos int M = pos - left + 1; //a[p]是a[left, right]中的第M小 if (K == M) return a[pos]; //找到第K小的数 if (K < M) randSelect(a, left, pos - 1, K); //向左边找第K小的数 else randSelect(a, pos + 1, right, K - M); //向右边找第K-M小 } } int a[1000100]; int main() { srand((unsigned)time(NULL)); int m, n; scanf("%d%d", &m, &n); for (int i = 0; i < m; i++) scanf("%d", &a[i]); int ans = randSelect2(a, 0, n - 1, n); printf("%d\n", m - ans + 1); return 0; }
http://codeup.cn/contest.php?cid=100000588
这个题目检查低位,其实就是将一个十进制数除了最高位外的其余位转换为另外一个十进制数(即它的低位部分)。
#include <cstdio> int main() { int N; while (scanf("%d", &N) != EOF) { int dN = N * N, low = 0, product = 1, flag = 0; while (dN / 10) { //dN还有最后一位(高位)时退出 low += (dN % 10) * product; // 逐渐检查低位 if (low == N) { printf("Yes!\n"); flag = 1; break; } product *= 10; dN /= 10; } if (!flag) printf("No!\n"); } }
一开始我还怀疑有没有这种数,不过确实有一个1089,只要检查1002(甚至更大一点)到1111为止的数就能够了,以后的数字*9会超出四位数。知道答案的话也能够直接打印1089(?)。
#include <cstdio> int main() { for (int i = 1002; i <= 1111; i++) { int reverseNum = i / 1000 + i % 1000 / 100 * 10 + i % 100 / 10 * 100 + i % 10 * 1000; if (i * 9 == reverseNum) printf("%d\n", i); } return 0; }
朴素的暴力解法。不过我以前不当心写出来这样的判断条件if (i + j + k == 100 && 5 * i + 3 * j + (double)(1 / 3) * k <= n)
,致使最小鸡的价格为0(?)……(double)类型转换使用要细心。
#include <cstdio> int main() { double n; while (scanf("%lf", &n) != EOF) { //暴力解法 int big = n / 5, small = n / 3, little = 3 * n; //整数只 for (int x = 0; x <= big; x++) { for (int y = 0; y <= small; y++) { for (int z = 0; z <= little; z++) { double sum = 5 * x + 3 * y + (double)z / 3; //浮点数总价 if (x + y + z == 100 && sum <= n) { printf("x=%d,y=%d,z=%d\n", x, y, z); } } } } } return 0; }
#include <cstdio> int main() { for (int a = 1; a <= 9; a++) { for (int b = 1; b <= 9; b++) { for (int c = 0; c <= 9; c++) { if (a * 100 + b * 10 + c + b * 100 + c * 10 + c == 532) { printf("%d %d %d\n", a, b, c); } } } } return 0; }
这个题目容易粗心,我提交错了两次。
#include <cstdio> int main() { int a[20]; while (scanf("%d", &a[0]) != EOF) { int hashTable[12] = {0}; //1-10 要放在里面 hashTable[a[0]]++; // 容易忘记统计第一个输入的数字 for (int i = 1; i < 20; i++) { scanf("%d", &a[i]); hashTable[a[i]]++; } int m = 0; for (int i = 1; i <= 10; i++) { //只有某个数出现次数更大时更新m if (hashTable[i] > hashTable[m]) m = i; } printf("%d\n", m); } return 0; }
这个题目,其实也简单,看看矩阵乘法的定义就好了。不过在结果矩阵上,由于有多组输入数据,所以必须在while内部申请,而且每一次申请要顺便清零,否则就会答案错误50
。
#include <cstdio> int main() { int x, i, j, k; while (scanf("%d", &x) != EOF) { int a[2][3], b[3][2], c[2][2] = {0}; for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) { if (!i && !j) a[0][0] = x; else scanf("%d", &a[i][j]); } } for (i = 0; i < 3; i++) { for (j = 0; j < 2; j++) { scanf("%d", &b[i][j]); } } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 3; k++) { c[i][j] += a[i][k] * b[k][j]; } } } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { printf("%d", c[i][j]); if (j < 2) printf(" "); } printf("\n"); } } return 0; }
???和问题D同样的题目?
#include <cstdio> int main() { for (int a = 1; a <= 9; a++) { for (int b = 1; b <= 9; b++) { for (int c = 0; c <= 9; c++) { if (a * 100 + b * 10 + c + b * 100 + c * 10 + c == 532) { printf("%d %d %d\n", a, b, c); } } } } }
等差数列求和。
#include <cstdio> int main() { int m; scanf("%d", &m); while (m--) { int N; scanf("%d", &N); int ans = N >= 0 ? 3 * (N * N + N) / 2 : - 3 * (N * N - N) / 2; printf("%d\n", ans); } return 0; }
又一个一样的题目……
#include <cstdio> int main() { printf("1089\n"); return 0; }
能够像我这么算多项式求和,也可使用秦九韶的方法。
#include <cstdio> int f(int max, int coef[], int x) { int product = 1, sum = 0; for (int i = 0; i <= max; i++) { sum += coef[i] * product; product *= x; } return sum; } int f1(int max, int coef[], int x) { //多项式系数由低阶向高阶存储 int sum = 0; for (int i = max; i >= 0; i--) { sum = sum * x + coef[i]; //秦九韶算法 } return sum; } int main() { int m; scanf("%d", &m); while (m--) { int n; scanf("%d", &n); int coef[n + 1]; for (int i = 0; i <= n; i++) { scanf("%d", &coef[i]); } int x; scanf("%d", &x); printf("%d\n", f1(n, coef, x)); } return 0; }
立方根的逼近迭代方程是y(n+1) = y(n)*2/3 + x/(3*y(n)*y(n))
,其中y0=x。求给定的x通过n次迭代后立方根的值。
4654684 1 65461 23
3103122.666667 40.302088
#include <cstdio> int main() { double x; int n; while (scanf("%lf%d", &x, &n) != EOF) { double rootX = x; for (int i = 0; i < n; i++) { rootX = rootX * 2 / 3 + x / (3 * rootX * rootX); } printf("%.6f\n", rootX); } return 0; }
#include <cstdio> int main() { int n; while (scanf("%d", &n) != EOF) { int sum = 0; for (int i = 1; i <= n; i++) { if (i % 7 != 0 && i % 10 != 7 && i / 10 != 7) { sum += i * i; } } printf("%d\n", sum); } return 0; }
这个问题能够描述成任给一个整数 N,若是N是奇数,输出0 0
(鸡兔没有奇数只脚),不然若是N是4的倍数,输出N / 4 N / 2
(最少全是兔子,最多全是鸡),若是N 不是4 的倍数,输出N/4+1 N/2
(最少是N/4只兔子+1只鸡,最多全是鸡)。这是一个通常的计算题,只要实现相应的判断和输出代码就能够了。
题目中说明了输入整数在一个比较小的范围内,因此只须要考虑整数运算。
#include <cstdio> int main() { int n; scanf("%d", &n); while (n--) { int N; scanf("%d", &N); if (N & 1) printf("0 0\n"); else { if (N % 4) { printf("%d %d\n", N / 4 + 1, N / 2); } else { printf("%d %d\n", N / 4, N / 2); } } } return 0; }
http://codeup.cn/contest.php?cid=100000589
题目描述
The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set.
For example, the LCM of 5, 7 and 15 is 105.
2 2 3 5 3 4 6 12
15 12
两个正整数a,b的最小公倍数等于a / gcd(a,b) * b
。
#include <cstdio> int gcd(int a, int b) { return !b ? a : gcd(b, a % b); } int lcm(int a, int b) { return a / gcd(a, b) * b; } int main() { int n; scanf("%d", &n); while (n--) { int m; scanf("%d", &m); int a, b; scanf("%d", &a); for (int i = 1; i < m; i++) { scanf("%d", &b); a = lcm(a, b); } printf("%d\n", a); } return 0; }
输入两个正整数,求其最大公约数。
49 14
7
#include <cstdio> int gcd(int a, int b) { return !b ? a : gcd(b, a % b); } int main() { int a, b; while (scanf("%d%d", &a, &b) != EOF) { printf("%d\n", gcd(a, b)); } }
http://codeup.cn/contest.php?cid=100000566
咱们定义以下矩阵:
1/1 1/2 1/3 1/2 1/1 1/2 1/3 1/2 1/1
矩阵对角线上的元素始终是1/1,对角线两边分数的分母逐个递增。请求出这个矩阵的总和。
1 2 3 4 0
1.00 3.00 5.67 8.83
这个题目只用分开看就好作了,1的数量为N,1/2的数量为2*(N-1),以此类推。求和便可。
#include <cstdio> int main() { int N; while (scanf("%d", &N), N) { double sum = 0.0; for (int i = 1; i <= N; i++) { sum += (1.0 / i) * (N + 1 - i) * 2; } printf("%.2f\n", sum - N); //前面多加了N*1 } return 0; }
这道题用通常求素数的方法也能作,毕竟n未超过105级别,O(n*sqrt(n))
的复杂度也能够。
#include <cstdio> bool isPrime(int x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; } int main() { int n; //n最大为4次方级别 while (scanf("%d", &n) != EOF) { int Prime[n + 10] = {0}, pNum = 0; for (int i = 2; i < n; i++) { if(isPrime(i) && i % 10 == 1) { //若是i是素数且个位为1 Prime[pNum++] = i; //记录i } } if (pNum) { for (int i = 0; i < pNum; i++) { printf("%d", Prime[i]); if (i < pNum - 1) printf(" "); else printf("\n"); } } else printf("-1\n"); } }
将maxn由10e6改为1000000就经过了,否则就是运算错误0……什么垃圾判题机,浪费我时间好吧。或许由于科学记数法是表示浮点数,不能做为数组大小。
#include <cstdio> const int maxn = 1000000; int Prime[maxn], pNum = 0; bool p[maxn] = {0}; //是素数就为false void findPrime() { for (int i = 2; i < maxn; i++) { if (!p[i]) { Prime[pNum++] = i; for (int j = i + i; j < maxn; j += i) { p[j] = true; } } } } int main() { int k; findPrime(); while (scanf("%d", &k) != EOF) { printf("%d\n", Prime[k - 1]); } return 0; }
这个问题是找出对于一个给定的[4,215]内的偶数even,存在多少组不一样的质数对(p1, p2)知足p1+p2=even
。
必备的起始点是素数表,采用埃氏筛法,O(n log logn)的复杂度。而后,双指针在素数表上滑动,计算对数便可。
#include <cstdio> const int maxn = 100000; int prime[maxn], pNum = 0; bool p[maxn] = {0}; void findPrime() { for (int i = 2; i < maxn; i++) { if (p[i] == false) { prime[pNum++] = i; for (int j = i + i; j < maxn; j += i) { p[j] = true; } } } } int main() { int even; findPrime(); while (scanf("%d", &even), even) { int cnt = 0; for (int i = 0, j = pNum - 1; i <= j;) { if (prime[i] + prime[j] == even) { cnt++; i++; j--; } else if (prime[i] + prime[j] > even) { j--; } else { i++; } } printf("%d\n", cnt); } return 0; }
题目描述
求1-n内的完数,所谓的完数是这样的数,它的全部因子相加等于它自身,好比6有3个因子1,2,3,1+2+3=6,那么6是完数。即完数是等于其全部因子相加和的数。
6
6
这个题目,不要受到书上面求质因子分解的影响,n的因子集合定义为[1, n)范围内能整除n的全部数,这里的因子包括1,这些因子相乘不等于n。28其因子集合为{1, 2, 4, 7, 14}
,质因子分解为28=2^2 * 7
,二者不一样。
所以,本题其实很简单,只需采用枚举[1, a)的全部因子并相加的方法判断a是否是完数,并对1-n范围内的全部数判断一遍就能够了。
另外,咱们注意到,因子的集合,除去1后是关于sqrt(n)对称的,如2*14=28,4*7=28
。另外一个例子36的因子集合{1, 2, 3, 4, 6, 9, 12, 18}
,也同样如此。
本题由于题目数据范围较小,不用这么优化。像问题 D: 约数的个数
与本题很是类似,约数集合不只包括1,也包括n自己,彻底对称,若是运行超时,就能够只算<=sqrt(n)的一半集合。
#include <cstdio> bool checkFullNum(int n) { int sum = 0; for (int i = 1; i < n; i++) { if (n % i == 0) { //i是n的因子 sum += i; } } if (sum == n) return true; //是完数返回true else return false; } int main() { int n; while (scanf("%d", &n) != EOF) { int ans[1000], k = 0; for (int i = 1; i <= n; i++) { //求出1到n的全部完数 if (checkFullNum(i) == true) ans[k++] = i; } for (int i = 0; i < k; i++) { printf("%d", ans[i]); if (i < k - 1) printf(" "); else printf("\n"); } } }
同样的题目!
质因子分解的代码片和方法都在如下的代码中了,也不必多说什么。
#include <cstdio> #include <cmath> struct factor { int x, cnt; //x为质数因子, cnt为x个数 }; const int maxn = 100020; int Prime[maxn], pNum = 0; bool p[maxn] = {false}; void Find_Prime() { for (int i = 2; i < maxn; i++) { if (p[i] == false) { Prime[pNum++] = i; for (int j = i + i; j < maxn; j += i) { p[j] = true; } } } } int main() { int n; Find_Prime(); while (scanf("%d", &n) != EOF) { struct factor fac[10]; int sqr = (int)sqrt(1.0 * n); int num = 0; //num为n的不一样质因子的个数 ; //枚举素数表中根号n之内的质因子 for (int i = 0; i < pNum && Prime[i] <= sqr; i++) { if (n % Prime[i] == 0) { //若是Prime[i]是n的质因子 fac[num].x = Prime[i]; //记录该质因子 fac[num].cnt = 0; while (n % Prime[i] == 0) { //计算出该质因子的个数 fac[num].cnt++; n /= Prime[i]; } num++; //不一样质因子个数+1 } //若是n为1, 说明n的质因子所有<=sqrt(n), 及时退出 if (n == 1) break; } if (n != 1) { //若是没法被根号n之内的质因子除尽 fac[num].x = n; //那么必定有一个大于根号n的质因子 fac[num++].cnt = 1; //即此时的n } int sum = 0; //计算所有质因子的总个数, 对于相同的质因数须要重复计算 for (int i = 0; i < num; i++) sum += fac[i].cnt; printf("%d\n", sum); } return 0; }
约数集合不只包括1,也包括n自己,彻底对称。36的约数集合{1, 2, 3, 4, 6, 9, 12, 18, 36}
,以6为对称。由此能够只算到sqrt(n),优化计算一个数约数的时间到O(√n),整体时间复杂度为O(n√n)。
#include <cstdio> #include <cmath> int main() { int n; while (scanf("%d", &n), n) { for (int i = 0; i < n; i++) { int t, cnt = 0; scanf("%d", &t); int sqr = (int)sqrt(1.0 * t); for (int i = 1; i <= sqr; i++) { if (t % i == 0) cnt += 2; //如1和t自己, 一次性算2个 if (i * i == t) cnt--; //如36, 做为约数集合的对称轴6只算一次 } printf("%d\n", cnt); } } return 0; }
这一道题目和问题A、问题D都有必定的联系,能够一块儿思考。
#include <cstdio> int check(int n) { int sum = 0; for (int i = 1; i < n; i++) { sum += (n % i == 0) ? i : 0; } if (sum == n) return 0; else if (sum > n) return 1; else return 2; } int main() { int E[100], G[100], pE = 0, pG = 0; for (int i = 2; i <= 60; i++) { switch(check(i)) { case 0: E[pE++] = i; break; case 1: G[pG++] = i; break; case 2: break; } } printf("E: "); //打印完数 for (int i = 0; i < pE; i++) { printf("%d", E[i]); if (i < pE - 1) printf(" "); else printf("\n"); } printf("G: "); //打印盈数 for (int i = 0; i < pG; i++) { printf("%d", G[i]); if (i < pG - 1) printf(" "); else printf("\n"); } return 0; }
http://codeup.cn/contest.php?cid=100000593
题目描述:实现一个加法器,使其可以输出a+b的值。
6 8 2000000000 30000000000000000000
14 30000000002000000000
要实现1千位的加法,非得要构建大整数结构不可,值得一提的是有的人使用字符数组,可是我认为,字符数组除了在高精度与低精度的乘法和除法上面还有优点(毕竟不用本身构建结构),在加法减法上面都没有优点,须要面对逆位存储低位不对齐带来的问题。
#include <cstdio> #include <cstring> struct bign { int d[1100], len; bign() { memset(d, 0, sizeof(d)); len = 0; } }; bign change(char str[]) { /* 将逆位存储的字符数组转变为顺位存储的bign */ bign a; a.len = strlen(str); //bign的长度就是字符串的长度 for (int i = 0; str[i]; i++) a.d[i] = str[a.len - i - 1] - '0'; //逆着赋值 return a; } int compare(bign a, bign b) { /* 比较两个bign变量, 先比较长度, 再从高位到低位进行比较 */ if (a.len > b.len) return 1; //a大 else if (a.len < b.len) return -1; //a小 else { for (int i = a.len - 1; i >= 0; i--) { if (a.d[i] > b.d[i]) return 1; //a大 else if (a.d[i] < b.d[i]) return -1; //a小 } } return 0; //两数相等 } bign add(bign a, bign b) { bign c; int carry = 0; //carry是进位 for (int i = 0; i < a.len || i < b.len; i++) {//以较长的为界限 int t = a.d[i] + b.d[i] + carry; c.d[c.len++] = t % 10; carry = t / 10; } if (carry) c.d[c.len++] = carry; return c; } bign print(bign a) { for (int i = a.len - 1; i >= 0; i--) { printf("%d", a.d[i]); } } int main() { char s1[1100], s2[1100]; while (scanf("%s%s", s1, s2) != EOF) { bign a = change(s1); bign b = change(s2); print(add(a, b)); printf("\n"); } return 0; }
题目描述:输入一个正整数N,输出N的阶乘。
0 4 7
1 24 5040
这一题我对0进行特判,对小于等于10的N使用fac函数计算,大于10的N使用大整数乘法,毕竟N的最大值能够是1000,已经远远超出long long范围了。
#include <cstring> #include <cstdio> int fac(int n) { int ans = 1; for (int i = 1; i <= n; i++) { ans *= i; } return ans; } struct bign { int d[10000], len; bign() { memset(d, 0, sizeof(d)); len = 0; } }; bign multi(bign a, int b) { //高精度与低精度的乘法 bign c; int carry = 0; for (int i = 0; i < a.len; i++) { int t = a.d[i] * b + carry; c.d[c.len++] = t % 10; //个位做为该位结果 carry = t / 10; //高位部分做为新的进位 } while (carry != 0) { //乘法的进位可能不止一位, 用while c.d[c.len++] = carry % 10; carry /= 10; } return c; } void print(bign a) { for (int i = a.len - 1; i >= 0; i--) { printf("%d", a.d[i]); } } int main() { int N; while (scanf("%d", &N) != EOF) { if (N == 0) printf("1\n"); else if (N <= 10) printf("%d\n", fac(N)); else { bign a, temp; a.len = 1; a.d[0] = 1; for (int i = 2; i <= N; i++) { a = multi(a, i); } print(a); printf("\n"); } } return 0; }
题目描述:求2个浮点数相加的和。题目中输入输出中出现浮点数都有以下的形式:
P1P2...Pi.Q1Q2...Qj
,对于整数部分,P1P2…Pi是一个非负整数;对于小数部分,Qj不等于0。
2 3.756 90.564 4543.5435 43.25
94.32 4586.7935
题目描述:将M进制的数X转换为N进制的数输出。
10 2 11
1011
#include <iostream> #include <cstdio> #include <string> #include <algorithm> using namespace std; string conversion(int m, string s, int n) { string b; int len = s.size(); for (int i = 0; i < len; ) { //当十进制字符还未除完时继续循环 int rest = 0, digit, x; //余数 for (int j = i; j < len; j++) { if (s[j] >= '0' && s[j] <= '9') digit = s[j] - '0'; else if (s[j] >= 'A' && s[j] <= 'Z') digit = s[j] - 'A' + 10; int temp = (rest * m + digit), x = temp / n; if (x >= 0 && x <= 9) s[j] = x + '0'; //一位字符的变化 else if (x >= 10 && x <= 36) s[j] = x - 10 + 'A'; rest = temp % n; //这一位的余数=(上一位余数乘权+这一位数)%取余 } if (rest >= 0 && rest <= 9) b += char(rest + '0'); //从低位向高位存入取余的字符 else if (rest >= 10 && rest <= 36) b += char(rest + 'a' - 10); while (s[i] == '0') i++;//跳过这一次产生的高位的0 //12345 / 2 变成06172 那么下次跳过了数字为0的下标, 从6开始 ,可是下标老是以n结束 } return b; } int main() { int M, N; string a,b,c; while (scanf("%d%d", &M, &N) != EOF) { cin >> a; b = conversion(M, a, N); reverse(b.begin(), b.end()); cout << b << endl; } return 0; }
#include<stdio.h> #include<string.h> struct bign{ int d[1010]; int len; bign(){ len = 0; memset(d, 0, sizeof(d)); } }; bign change(char a[]) { bign t; for(int i=strlen(a)-1; i>=0; i--) { if(a[i]>='0'&&a[i]<='9') t.d[t.len++] = a[i]-'0'; else t.d[t.len++] = (a[i]-'A'+10); } return t; } int main() { int m, n; while(scanf("%d%d",&m,&n)!=EOF) { getchar();//消去换行 char x[10001]; scanf("%s",x); bign a; a = change(x); char ans[1001]; int len = strlen(x),index=0; while(a.len>0)//a.len==0即展转相除到了最后 { int carry = 0; for(int i=a.len-1; i>=0; i--) { int temp = a.d[i] + carry*m; carry = temp % n; a.d[i] = temp/n; } while(a.d[a.len-1]==0) a.len--; if(carry>=0&&carry<=9) ans[index++] = carry+'0'; else ans[index++] = carry-10+'a'; } for(int i=index-1; i>=0; i--) printf("%c", ans[i]); printf("\n"); } return 0; }
对N个长度最长可达到1000的数进行排序。
4 123 1234 12345 2345
123 1234 2345 12345
这一题我对scanf("%d")的使用方法更了解了,它调用后会先跳过换行、空格等符号,而后输入一个整数就结束了,下面的输入从整数以后开始,若是整数后面有换行符,并且咱们使用gets的话,第一个gets把这个换行符吸取掉就会中止,致使结果错误。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct bign { int d[2000], len; bign() { memset(d, 0, sizeof(d)); len = 0; } }; bign change(char str[]) { /* 将逆位存储的字符数组转变为顺位存储的bign */ bign a; a.len = strlen(str); //bign的长度就是字符串的长度 for (int i = 0; str[i]; i++) a.d[i] = str[a.len - i - 1] - '0'; //逆着赋值 return a; } void print(bign a) { for (int i = a.len - 1; i >= 0; i--) { printf("%d", a.d[i]); } } bool cmp(bign a, bign b) { if (a.len != b.len) return a.len < b.len; //从小到大排序 else { for (int i = a.len - 1; i >= 0; i--) { if (a.d[i] != b.d[i]) return a.d[i] < b.d[i]; //从小到大排序 } } return false; } int main() { int n; while (scanf("%d", &n) != EOF) { getchar(); //吸取n后面的换行符 bign total[n + 10]; char s[1100]; for (int i = 0; i < n; i++) { gets(s); total[i] = change(s); } sort(total, total + n, cmp); for (int i = 0; i < n; i++) { print(total[i]); printf("\n"); } } return 0; }
题目描述:对于一个十进制数A,将A转换为二进制数,而后按位逆序排列,再转换为十进制数B,咱们称B为A的二进制逆序数。
例如对于十进制数173,它的二进制形式为10101101,逆序排列获得10110101,其十进制数为181,181即为173的二进制逆序数。
985
623
10->2,除2取余倒排;2->10,按位乘权相加
),大整数。#include <cstdio> #include <cstring> struct bign { int d[5000], len; bign() { memset(d, 0, sizeof(d)); len = 0; } }; void print(bign a) { for (int i = a.len - 1; i >= 0; i--) { printf("%d", a.d[i]); } printf("\n"); } bign change(char str[]) { bign t; t.len = strlen(str); for (int i = 0; i < t.len; i++) { t.d[i] = str[t.len - i - 1] - '0'; } return t; } bign divideInt(bign a, int b, int &r) { //r为余数 bign t; t.len = a.len; for (int i = a.len - 1; i >= 0; i--) { r = r * 10 + a.d[i]; if (r < b) t.d[i] = 0; else { t.d[i] = r / b; r %= b; } } //去除高位的0 while (t.len >= 1 && t.d[t.len - 1] == 0) t.len--; return t; } bign multiInt(bign a, int b) { bign t; int carry = 0; for (int i = 0; i < a.len; i++) { int temp = a.d[i] * b + carry; t.d[t.len++] = temp % 10; carry = temp / 10; } while (carry) { t.d[t.len++] = carry % 10; carry /= 10; } return t; } bign addInt(bign a, int b) { bign t; int carry; t.d[t.len] = a.d[0] + b; carry = t.d[t.len] / 10; t.d[t.len++] %= 10; for (int i = 1; i < a.len; i++) { t.d[t.len] = a.d[i] + carry; carry = t.d[t.len] / 10; t.d[t.len++] %= 10; } while (carry) { t.d[t.len++] = carry % 10; carry /= 10; } return t; } int t[10000], len = 0; bign ArrToBign(int b) { //将b进制数组s(逆位存储)转换成10进制大整数 bign sum; for (int i = 0; i < len; i++) { sum = addInt(multiInt(sum, 2), t[i]); } return sum; } void BignToArr(bign a, int b, int s[]) { //将10进制大整数数转换成b进制数组s int r = 0; while (a.len > 0) { a = divideInt(a, b, r); t[len++] = r; r = 0; //从新清零 } } int main() { char A[1015]; while (scanf("%s", A) != EOF) { memset(t, 0, sizeof(t)); bign a = change(A); BignToArr(a, 2, t); bign ans = ArrToBign(2); print(ans); } return 0; }
#include <iostream> #include <cstdio> #include <string> #include <algorithm> using namespace std; string conversion(int m, string s, int n) { string b; int len = s.size(); for (int i = 0; i < len; ) { //当十进制字符还未除完时继续循环 int rest = 0; //余数 for (int j = i; j < len; j++) { int digit = s[j] - '0'; int temp = (rest * m + digit) % n;//这一位的余数=(上一位余数乘权+这一位数)%取余 s[j] = (rest * m + digit) / n + '0'; //一位字符的变化 rest = temp; } b += char(rest + '0'); //从低位向高位存入取余的字符 while (s[i] == '0') i++;//跳过这一次产生的高位的0 //12345 / 2 变成06172 那么下次跳过了数字为0的下标, 从6开始 ,可是下标老是以n结束 } return b; } int main() { string a,b,c; while (cin >> a){ b = conversion(10, a, 2); a = conversion(2, b, 10); reverse(a.begin(), a.end()); cout << a << endl; } }
http://codeup.cn/contest.php?cid=100000594
http://codeup.cn/contest.php?cid=100000595
要求将计算阶乘运算的函数写为fact(n),函数返回值的类型为float。输出返回值的时候要用%f
,若是用了%d
,就只会输出0了。
#include <cstdio> float fact(int n) { float ans = 1.0; for (int i = 1; i <= n; i++) { ans *= i; } return ans; } int main() { int m, n; while (scanf("%d%d", &m, &n) != EOF) { //计算组合数的公式 printf("%.0f\n", fact(m) / (fact(n) * fact(m - n))); } return 0; }
题目描述:组合数的计算虽然说简单但也不乏有些陷阱,这主要是由于语言中的数据类型在表示范围上是有限的。更况且还有中间结果溢出的现象,因此千万要当心。
5 2 18 13
10 8568
20的阶乘,已经大大超过了int的范围,可是尚未超出long long的范围,直接写一个阶乘函数的long long版就能够了。
#include <cstdio> typedef long long ll; ll fact(int n) { ll ans = 1; for (int i = 1; i <= n; i++) { ans *= i; } return ans; } int main() { int m, n; while (scanf("%d%d", &m, &n) != EOF) { printf("%lld\n", fact(m) / (fact(n) * fact(m - n))); } return 0; }
运行错误86???本地能够测试过,可是CodeUp错误。我这里想的是课程序号做为二维数组的行映射,选课的学生名映射到二维数组的列,每一行是个记录某学生是否选择该门课程的哈希表,该表能够称做课程的学生名单(Student List for Course)。
#include <cstdio> #include <cstring> int hashFunc(char s[]) { //3大写字母+1数字 int id = 0; for (int i = 0; i < 3; i++) { id = id * 26 + (s[i] - 'A'); } id = id * 10 + (s[3] - '0'); return id; } int main() { int N, K, cid, stuNum, id; char tempStr[6]; scanf("%d%d", &N, &K); bool cList[K + 1][26 * 26 * 26 * 10 + 1] = {false}; for (int i = 0; i < K; i++) { scanf("%d%d", &cid, &stuNum); while (stuNum--) { scanf("%s", tempStr); id = hashFunc(tempStr); cList[cid][id] = true; } } while (N--) { scanf("%s", tempStr); id = hashFunc(tempStr); int cour[K] = {0}, cnt = 0; for (int cid = 1; cid <= K; cid++) { if (cList[cid][id]) { cour[cnt++] = cid; } } printf("%s %d", tempStr, cnt); for (int t = 0; t < cnt; t++) { printf(" %d", cour[t]); } printf("\n"); } return 0; }
使用vector等重写后能够经过,以下,这其实是Course List for Student,是学生的课程表(即题目但愿咱们要输出的结果),每一行表明学生选的课程,是一个变长数组,可使用排序和size()函数直接输出答案。
#include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; //只有一个测试用例 int hashFunc(char s[]) { //用hash存学生名, 3大写字母+1数字 int id = 0; for (int i = 0; i < 3; i++) { id = id * 26 + (s[i] - 'A'); } id = id * 10 + (s[3] - '0'); return id; } vector<int> stuOfCours[175761]; //即学生编号数26*26*26*10+1 int main() { int N, K, cid, stuNum, id; //课程ID 课程学生人数 学生ID char tempStr[6]; scanf("%d%d", &N, &K); while (K--) { scanf("%d%d", &cid, &stuNum); while (stuNum--) { scanf("%s", tempStr); id = hashFunc(tempStr); stuOfCours[id].push_back(cid); //一个学生的课程表向量 } } while (N--) { scanf("%s", tempStr); id = hashFunc(tempStr); sort(stuOfCours[id].begin(), stuOfCours[id].end()); printf("%s %d", tempStr, stuOfCours[id].size()); for (vector<int>::iterator it = stuOfCours[id].begin(); it != stuOfCours[id].end(); it++) { printf(" %d", *it); } printf("\n"); } return 0; }
从学生的课程表转换输出课程的学生名单,如今我已经轻车熟路了。使用vector、string的代码以下,确实简单了不少:
#include <cstdio> #include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; vector<string> studentList[2510]; int main() { int N, K, n, cid; scanf("%d%d", &N, &K); while (N--) { string temp; cin >> temp >> n; while (n--) { scanf("%d", &cid); studentList[cid].push_back(temp); } } for (int i = 1; i <= K; i++) { printf("%d %d\n", i, studentList[i].size()); sort(studentList[i].begin(), studentList[i].end()); for (int j = 0; j < studentList[i].size(); j++) { cout << studentList[i][j] << endl; //string要用cout打印 } } return 0; }
题目说的是,先计算两个集合去重后的交集Nc,而后计算两个集合并集并去重Nt,二者的元素个数相除。我下面这么写时间超限83,估计是计算两个集合交集元素个数时超时了,本身手动遍历两个集合就是O(n2)。并且本题只有一个测试用例。
#include <cstdio> #include <set> using namespace std; int main() { int N, n, temp, M, set1, set2; double ans; scanf("%d", &N); set<int> AllSet[N + 2]; for (int t = 1; t <= N; t++) { scanf("%d", &n); for