http://codeup.cn/contest.php?cid=100000566
#include
int main()
{
printf("%s", "This is my first c program!");
return 0;
}
#include
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
int main()
{
int a, b;
scanf("%d%d", &a, &b);
printf("%d", a+b);
return 0;
}
#include
#include
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
int main()
{
/* 从键盘输入三个字符BOY,然后把他们输出到屏幕上
输入 BOY三个字符,中间无分隔符
输出 BOY,注意末尾的换行 */
char s[10];
scanf("%s", s);
printf("%s", s);
return 0;
}
http://codeup.cn/contest.php?cid=100000567
#include
#include
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
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
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
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
int main()
{
double income, bonus;
scanf("%lf", &income);
/* 某企业发放的奖金根据利润提成。利润I低于或等于100000时,奖金可提10%;
利润(1000001000000元时,超过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=100000567
#include
int main()
{
int i=1, sum=0;
while (i <= 100) {
sum += i;
i++;
}
printf("%d\n", sum);
return 0;
}
/*---------------------------------------------------*/
#include
int main()
{
printf("%d\n", 100 * (100 + 1) / 2);
return 0;
}
#include
int main()
{
int i = 0, sum = 0;
do {
sum += i;
i++;
} while (i <= 100);
printf("%d\n", sum);
return 0;
}
#include
int main()
{
int sum = 0;
for (int i = 0; i < 100; i++, sum+=i);
printf("%d\n", sum);
return 0;
}
#include
int main()
{
int n;
scanf("%d", &n);
printf("%d\n", n * (n + 1) / 2);
return 0;
}
#include
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
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
/* 用如下公式 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
/*输入 一个不超过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
/* 有一个分数序列: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
/* 第一行输入以空格分隔的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
/* 将一个长度为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
#include
/*
输入 输入只包含一个正整数n,表示将要输出的杨辉三角的层数。
输出 对应于该输入,请输出1-相应层数的杨辉三角,每一层的整数之间用一个空格隔开, 最多输出10层 */
int main()
{
int n, a[10] = {1, 1};
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
/* 打印第1、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
#include
/* 第一个字母变成第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;
}
这个题目似乎只是对等长字符串进行比较,如果不等长的话…需要修改一下。
#include
#include
/* 比较两个字符串s1和s2的大小,如果s1>s2,则输出一个正数;
若s1=s2,则输出0;若s1
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
/* 输入 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数列的方法。
#include
/* 输入 无
输出 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
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
/* 输入 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
#include
/* 输入 输入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;
}
我这里使用的是原地修改, 懒得返回值了。
#include
#include
/* 输入 一行字符串。
输出 输入字符串反序存放后的字符串。单独占一行。*/
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
/* 输入 两个用空格隔开的整数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
/*输入 三个用空格隔开的整数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
/* 给定字符串定义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
#include
/* 输入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
/*输入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
#include
/* 输入第一行有一个整数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
#include
/* 输入 第一行有一个整数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
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
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
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;
}
多点测试中有如下结构用于反复执行程序的核心部分:
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
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
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
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
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
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
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
int main()
{
int a, b;
while (scanf("%d%d", &a, &b) != EOF)
printf("%d\n\n", a + b);
return 0;
}
#include
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
#include
/*有一个长度为整数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
#include
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
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
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
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
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
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
#include
/* 给出字符如'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
#include
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
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
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
#include
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
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
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
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
#include
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
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
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
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
#include
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
#include
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
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
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
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
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
#include
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
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
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
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
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
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
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
#include
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
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
#include
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
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
#include
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
#include
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
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
#include
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
#include
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
#include
#include
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
#include
#include
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
#include
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
#include
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
#include
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
#include
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
#include
#include
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
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
#include
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
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
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
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
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
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
#include
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]
来说需要两个点如3、5,才能确保每个闭区间内都至少有一个点。代码写法也是类似的。
#include
#include
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
#include
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
#include
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
#include
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
#include
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
#include
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
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
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
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
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
#include
#include
/* 将数组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
#include
#include
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
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
#include
#include
#include
#include
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
#include
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
#include
#include
#include
#include
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
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
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
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
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
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
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
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
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
int main() {
printf("1089\n");
return 0;
}
可以像我这么算多项式求和,也可以使用秦九韶的方法。
#include
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
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
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
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
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
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
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
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
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
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
bool checkFullNum(int n) {
int sum = 0;
for (int i = 1; i < n; i++) {