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