程式設計菜雞的程式設計之路
雖然沒有選C2這門課程,不過還是去聽下課順便完成作業吧,反正這學期課挺少的。
小題就算了不寫了。
子串逆置
【問題描述】 輸入兩行字串s和t(s和t可以含空格,length(t)≤length(s)≤50),將s串中首次與t匹配的子串逆置,並將處理後的s串輸出。 【輸入形式】 輸入檔案為當前目錄下的invertsub.in。 檔案中有兩行字串s和t,分別以換行符作為結束符,其中換行符可能是Linux下的換行符,也可能是Windows下的換行符。 【輸出形式】 輸出檔案為當前目錄下的invertsub.out。 輸出檔案只有一行,包含一個串,為要求的輸出結果。行末要輸出一個回車符。 【輸入樣例】 helloworld llowor 【輸出樣例】 herowollld 【時間限制】 1s 【空間限制】 65536KB 【上傳檔案】 上傳c語言源程式,檔名為invertsub.c。
在本地測試的時候文字最後沒加換行debug了好久= =,逆置還是挺基礎和簡單的。不過這題用到strstr返回的是出現的地址,所以用指標寫。
#include<stdio.h> #include<string.h> void rev(char *first, char *last) { int temp; while (first < last) { temp = *first; *first = *last; *last = temp; first++; last--; } } int main() { char s[52], t[52], *p; FILE *in, *out; in = fopen("invertsub.in", "r"); out = fopen("invertsub.out", "w"); fgets(s, 52, in); fgets(t, 52, in); s[strlen(s) - 1] = '\0'; t[strlen(t) - 1] = '\0'; if ((p = strstr(s, t)) != NULL) rev(p, p + strlen(t) - 1); fprintf(out, "%s\n", s); fclose(in); fclose(out); }
區間
【問題描述】 給定n個閉區間[ai, bi](1 <= i <= n),這些區間的並可以表示為一些不相交的閉區間的並。要求在這些表示方式中找出包含不相交區間數目最少的方案。 【輸入形式】 輸入檔案為當前目錄下的prz.in。 該檔案包含n行(3 <= n <= 50000),每行各包括兩個以空格分隔的整數ai 和 bi,表示一個區間[ai, bi](1 <= ai <= bi <= 1000000)。 【輸出形式】 輸出檔案為當前目錄下的prz.out。 該檔案內容為計算出來的不相交的區間。每一行都是對一個區間的描述,包括兩個以空格分開的整數,分別為區間的下界和上界。 輸出時將各區間按照升序排列輸出。這裡說兩個區間[a, b]和[c, d]是按照升序排列的,是指a <= b < c <= d。 【輸入樣例】 5 6 1 4 10 10 6 9 8 10 【輸出樣例】 1 4 5 10 【時間限制】 1s 【空間限制】 65536KB 【上傳檔案】 上傳c語言源程式,檔名為prz.c。
這次裡面算是最難的一道了吧。分析步驟如下:
(1)首先根據區間的下界排序,這裡如果用複雜度的排序(我用的選擇排序)好像會超時,所以用快排吧(我這是手寫的快排,用自帶的qsort應該會比較快)
(2)逐個比對,如果區間能夠相交則合併,記錄最大的上界。如果一個區間的下界比之前區間的上界還大,說明這兩個區間必定不相交,輸出之前的區間。
#include<stdio.h>
struct prz {
int high;
int low;
}p[50007];
void qsort(struct prz p[], int left, int right);
void print(struct prz p[], int n, FILE *out);
void swap(struct prz p[], int i, int j);
int main()
{
FILE *in, *out;
in = fopen("prz.in", "r");
out = fopen("prz.out", "w");
int i;
int cnt = 0;
while ((fscanf(in, "%d%d", &p[cnt].low, &p[cnt].high)) != EOF)
{
cnt++;
}
qsort(p, 0, cnt - 1);
print(p, cnt, out);
fclose(in); fclose(out);
}
void qsort(struct prz p[], int left, int right)
{
struct prz temp;
int i, j;
if (left < right) {
j = left;
for (i = left + 1; i <= right; i++) {
if (p[i].low < p[left].low)
swap(p, i, ++j);
}
swap(p, j, left);
qsort(p, left, j - 1);
qsort(p, j + 1, right);
}
}
void print(struct prz p[], int n, FILE *out)
{
int last = 0;
int i;
fprintf(out, "%d ", p[0].low);
for (i = 1; i < n; i++)
{
if (p[i].low > p[last].high)
{
fprintf(out, "%d\n%d ", p[last].high, p[i].low);
last = i;
}
else if (p[i].high > p[last].high)
last = i;
}
fprintf(out, "%d\n", p[last].high);
}
void swap(struct prz p[], int i, int j)
{
struct prz temp = p[i];
p[i] = p[j];
p[j] = temp;
}
兌換硬幣
【問題描述】
寫一個程式,從標準輸入上讀入一個正整數N(1 <= N <=1000),計算出N元人民幣兌換成1分、2分和5分的硬幣,有多少種可能的組合。將結果以整數的方式輸出到標準輸出上,佔一行。
【輸入形式】
正整數N。(1 <= N <=1000)
【輸出形式】
整數。
【輸入樣例】
1
【輸出樣例】
541
【時間限制】
1s
【空間限制】
65536KB
【上傳檔案】
上傳c語言源程式,檔名為nickle.c。
水題。暴力做會超時。
事實上如果遍歷5分硬幣的數量,根據剩餘金額可以直接算出來有幾種組合,因為只需要數2分硬幣有幾種情況,剩下的1分都能補足。我稍微化簡了一下所以看著不是很清晰,湊合吧。
#include<stdio.h>
int count(int n)
{
int i;
int cnt = 0;
for (i = 0; i <= n * 20; i++)
{
cnt += (n * 100 - i * 5) / 2 + 1;
}
return cnt;
}
int main()
{
int n;
scanf("%d", &n);
printf("%d", count(n));
}
實數格式識別
【問題描述】
合法的實數書寫格式分一般格式和科學格式兩種。分別描述如下:
一般格式為常見的書寫格式,分為整數部分和小數部分兩部分,中間分用小數點.分隔。整數部分最開始可能含有正號或負號,之後為不含前導零的數字串;小數部分是由0-9十種字元組成的任意長的字串。當小數部分為0時,小數部分和小數點可以省略。
科學格式由係數部分和指數部分兩部分組成,中間用英文字母E分隔。係數部分為實數書寫的一般格式;指數部分為可帶有正負號數字串。
例如,+2、-1.56為一般格式的實數,而6.2E-2、-9E8為科學格式的實數。
只有小數點而沒有小數部分的書寫格式為不合法,例如,23.,23.E16均為不合法的實數書寫格式。
程式設計分析哪些數的書寫是正確的,是用哪種方式書寫的。
【輸入形式】
輸入檔案為當前目錄下的real.in。 該檔案包含一個字串(長度不超過20個字元),以回車符結束,表示一個數據(無多餘空格)。
【輸出形式】
輸出檔案為當前目錄下的real.out。 該檔案有一行。如果輸入資料的書寫是非法的,輸出Wrong;如果輸入資料是用一般格式書寫的,輸出“Format1”;如果該資料是用科學格式書寫的,輸出“Format2”。輸出的末尾均要以一個回車符作為結束。
【輸入樣例1】
+1.23
【輸出樣例1】
Format1
【輸入樣例2】
-5.1.1
【輸出樣例2】
Wrong
【輸入樣例3】
-5.1E-2
【輸出樣例3】
Format2
【時間限制】
1s
【空間限制】
65536KB
【上傳檔案】
上傳c語言源程式,檔名為real.c。
不難但是很繁瑣的一道題,思路可以用狀態機來完成,但是我怕出錯就沒這麼寫。一開始寫了一個超級繁瑣的版本後來改成下面這個版本。
普通格式與科學格式的特徵區別:E <普通格式> E [<符號>] <整數>
如果有E我們就用科學格式來判別,E前面是否為<普通格式>,後面是否為[符號]+整數。如果沒有E我們就判斷是否為普通格式。
普通格式的兩種型別:是否有小數點 [<符號>]<整數> . <整數> [<符號>]<整數>
所以我們根據有無小數點,判斷小數點前面和後面是否分別滿足條件即可。
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<ctype.h>
void judge(char s[], int length, FILE *out);
bool judgeDec(char s[], int first, int last);
bool judgeInt(char s[], int first, int last);
bool judgeExp(char s[], int fisrt, int last, int eindex);
int main()
{
char s[22];
FILE *in, *out;
in = fopen("real.in", "r");
out = fopen("real.out", "w");
fgets(s, 22, in);
s[strlen(s) - 1] = '\0';
int length = strlen(s);
judge(s, length, out);
close(in); close(out);
return 0;
}
void judge(char s[], int length, FILE *out)
{
int i;
for (i = 0; i < length; i++)
if (s[i] == 'E')
break;
if (i + 1 == length)
fprintf(out, "Wrong\n");
else if (i == length)
{
if (judgeDec(s, 0, length - 1))
fprintf(out, "Format1\n");
else
fprintf(out, "Wrong\n");
}
else
{
if (judgeExp(s, 0, length - 1, i))
fprintf(out, "Format2\n");
else
fprintf(out, "Wrong\n");
}
}
bool judgeDec(char s[], int first, int last)
{
int pindex;
int pflag = 0;
bool judge = false;
int i = (s[first] == '-' || s[first] == '+') ? first + 1 : first;
for (pindex = first; pindex <= last; pindex++)
if (s[pindex] == '.')
{
pflag++;
break;
}
if (!pflag)
judge = judgeInt(s, i, last);
else
judge = judgeInt(s, i, pindex - 1) && judgeInt(s, pindex + 1, last);
return judge;
}
bool judgeInt(char s[], int first, int last)
{
if (first > last)
return false;
while (isdigit(s[first]) && first <= last)
first++;
if (first == last + 1)
return true;
else
return false;
}
bool judgeExp(char s[], int first, int last, int eindex)
{
bool judge = false;
int i = (s[eindex + 1] == '-' || s[eindex + 1] == '+') ? eindex + 2 : eindex + 1;
judge = judgeDec(s, first, eindex - 1) && judgeInt(s, i, last);
return judge;
}
在judgeDec和judgeExp我沒有對left<=right進行規約, 因為呼叫時已經滿足了這個條件。
N!的分解
【問題描述】
將N!分解成素數冪的乘積。
【輸入形式】
從標準輸入讀取一個整數N(1 <= N <= 30000)。
【輸出形式】
結果列印到標準輸出。 輸出格式為:p1^k1*p2^k2…其中p1,p2…為質數且ki>1。當ki=1時只輸出pi,ki=0的項不輸出。分解式中的素數按從小到大輸出。
【輸入樣例】
5
【輸出樣例】
2^3*3*5
【時間限制】
1s
【空間限制】
65536KB
【上傳檔案】
上傳c語言源程式,檔名為decompose.c。
對2~N出現的每一個數,將其所有質因子加入質數表中記錄出現次數。不過我沒有記錄用質數表而是直接用陣列存,反正效果差不多= =
另外輸出的時候特判一下就行了
#include<stdio.h>
#define MAXNUM 30001
int prime[MAXNUM] = { 0 };
void gen_factor(int n, int prime[]);
void print(int n, int prime[]);
int main()
{
int n;
scanf("%d", &n);
gen_factor(n, prime);
print(n, prime);
}
void gen_factor(int n, int prime[])
{
int i, j, temp;
for (i = 2; i <= n; i++)
{
temp = i;
for (j = 2; j <= temp; j++)
{
if (temp % j == 0)
{
prime[j] ++;
temp /= j;
j--;
}
}
}
}
void print(int n, int prime[])
{
int i, first = 1;
for (i = 2; i <= n; i++)
{
if (prime[i] == 1)
{
if (first)
{
first = 0;
printf("%d", i);
}
else
printf("*%d", i);
}
else if (prime[i] > 1)
{
if (first)
{
first = 0;
printf("%d^%d", i, prime[i]);
}
else
printf("*%d^%d", i, prime[i]);
}
}
}
好好學吧,這學期儘量堅持一件事。把C2的平時練習都寫完然後寫部落格,看看能不能堅持這學期