題頭,本內容的題目和部份內容均來自博客:https://blog.csdn.net/ryo_218/article/details/79704030 ,在此感謝。html
1.ios
題目標題:高斯日記
大數學家高斯有個好習慣:不管如何都要記日記。
他的日記有個不同凡響的地方,他從不註明年月日,而是用一個整數代替,好比:4210
後來人們知道,那個整數就是日期,它表示那一天是高斯出生後的第幾天。這或許也是個好習慣,它時時刻刻提醒着主人:日子又過去一天,還有多少時光能夠用於浪費呢?
高斯出生於:1777年4月30日。
在高斯發現的一個重要定理的日記上標註着:5343,所以可算出那天是:1791年12月15日。
高斯得到博士學位的那天日記上標着:8113
請你算出高斯得到博士學位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
請嚴格按照格式,經過瀏覽器提交答案。
注意:只提交這個日期,不要寫其它附加內容,好比:說明性的文字。算法
硬是模擬出來了,其實直接數也行。。編程
#include <iostream> #include <cstdio> using namespace std; int day[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int main() { int flag = 0; int n; int sum = 0; int ans = 0; int year1, month1, day1; int year2, month2, day2; scanf("%d-%d-%d", &year1, &month1, &day1); scanf("%d", &n); //scanf("%d-%d-%d", &year2, &month2, &day2); //printf("%d-%d-%d\n", year1, month1, day1); for(int i = month1-1; i < 12; ++i) { if((year1%4==0&&year1%100!=0)||(year1%400==0)) { if(i==1) sum += day[i]+1; else sum += day[i]; } else sum += day[i]; } /* for(int i = 0; i < month2-1; ++i) { if((year2%4==0&&year2%100!=0)||(year2%400==0)) { if(i==1) sum += day[i]+1; else sum += day[i]; } else sum += day[i]; } */ //sum += (day2-day1+1); sum -= day1-1; /* for(int i = year1+1; i <= year2-1; ++i) { if((i%4==0&&i%100!=0)||i%400==0) { for(int j = 0; j < 12; ++j) { if(j==1) sum += day[j]+1; else sum += day[j]; } } else { for(int j = 0; j < 12; ++j) { sum += day[j]; } } } */ //printf("%d\n", sum); for(int i = year1+1; i <= 2019; ++i) { if((i%4==0&&i%100!=0)||i%400==0) { for(int j = 0; j < 12; ++j) { if(sum == n) { year2 = i; day2 = 1; month2 = j+1; flag = 1; break; } else if(sum > n) { flag = 1; year2 = i; if(j == 0) { int x = 11; day2 = day[x]-(sum-n); //printf("%d %d\n", day2, day[x]); month2 = 12; year2 = i-1; } else { int x = j-1; day2 = day[x]-(sum-n); //printf("%d %d\n", day2, j); month2 = j; } break; } else { if(j==1) sum += day[j]+1; else sum += day[j]; } } if(flag) break; } else { for(int j = 0; j < 12; ++j) { if(sum == n) { flag = 1; year2 = i; day2 = 1; month2 = j+1; break; } else if(sum > n) { flag = 1; year2 = i; if(j == 0) { int x = 11; day2 = day[x]-(sum-n); //printf("%d %d\n", day2, day[x]); month2 = 12; year2 = i-1; } else { int x = j-1; day2 = day[x]-(sum-n); //printf("%d %d\n", day2, j); month2 = j; } break; } else sum += day[j]; } if(flag) break; } if(flag) break; } printf("%d-%d-%d\n", year2, month2, day2); }
答案是: 1799-07-16數組
2.瀏覽器
標題:馬虎的算式
小明是個急性子,上小學的時候常常把老師寫在黑板上的題目抄錯了。
有一次,老師出的題目是:36 x 495 = ?
他卻給抄成了:396 x 45 = ?
但結果卻很戲劇性,他的答案居然是對的!!
由於 36 * 495 = 396 * 45 = 17820
相似這樣的巧合狀況可能還有不少,好比:27 * 594 = 297 * 54
假設 a b c d e 表明1~9不一樣的5個數字(注意是各不相同的數字,且不含0)
能知足形如: ab * cde = adb * ce 這樣的算式一共有多少種呢?
請你利用計算機的優點尋找全部的可能,並回答不一樣算式的種類數。
知足乘法交換律的算式計爲不一樣的種類,因此答案確定是個偶數。
答案直接經過瀏覽器提交。
注意:只提交一個表示最終統計種類數的數字,不要提交解答過程或其它多餘的內容。
ide
這題要注意互不相同的數字!函數
直接暴力:spa
#include <iostream> #include <cstdio> using namespace std; int main() { int ans = 0; for(int a = 1; a <= 9; ++a) { for(int b = 1; b <= 9; ++b) { for(int c = 1; c <= 9; ++c) { for(int d = 1; d <= 9; ++d) { for(int e = 1; e <= 9; ++e) { int x, y; int x1, y1, x2, y2; x1 = a*10+b; x2 = c*100+d*10+e; y1 = a*100+d*10+b; y2 = c*10+e; x = x1*x2; y = y1*y2; if(x == y && (a!=b)&&(a!=c)&&(a!=d)&&(a!=e)&&(b!=a)&&(b!=c)&&(b!=d)&&(b!=e)&&(c!=b)&&(c!=a)&&(c!=d)&&(c!=e)&&(d!=b)&&(d!=c)&&(d!=a)&&(d!=e)&&(e!=b)&&(e!=c)&&(e!=d)&&(e!=a)) ans++; } } } } } printf("%d\n", ans); }
答案: 142操作系統
3.
題目標題:第39級臺階
小明剛剛看完電影《第39級臺階》,離開電影院的時候,他數了數禮堂前的臺階數,剛好是39級!
站在臺階前,他忽然又想着一個問題:
若是我每一步只能邁上1個或2個臺階。先邁左腳,而後左右交替,最後一步是邁右腳,也就是說一共要走偶數步。那麼,上完39級臺階,有多少種不一樣的上法呢?
請你利用計算機的優點,幫助小明尋找答案。
要求提交的是一個整數。
注意:不要提交解答過程,或其它的輔助說明文字。
思路:步數爲1或者2。標記一個flag,往上一步!flag,當flag = 0的時候,說明右腳上,故當step == 39的時候flag == 0則符合題意。
#include <iostream> #include <cstdio> using namespace std; int ans = 0; void dfs(int step, int flag) { if(step == 39) { if(flag == 0) ans++; return; } if(step > 39) return; dfs(step+1, !flag); dfs(step+2, !flag); } int main() { dfs(0, 0); printf("%d\n", ans); }
4.
標題:黃金連分數
黃金分割數0.61803... 是個無理數,這個常數十分重要,在許多工程問題中會出現。有時須要把這個數字求得很精確。
對於某些精密工程,常數的精度很重要。也許你據說過哈勃太空望遠鏡,它首次升空後就發現了一處人工加工錯誤,對那樣一個龐然大物,其實只是鏡面加工時有比頭髮絲還細許多倍的一處錯誤而已,卻使它成了「近視眼」!!
言歸正傳,咱們如何求得黃金分割數的儘量精確的值呢?有許多方法。
比較簡單的一種是用連分數:
1
黃金數 = ---------------------
1
1 + -----------------
1
1 + -------------
1
1 + ---------
1 + ...
這個連分數計算的「層數」越多,它的值越接近黃金分割數。
請你利用這一特性,求出黃金分割數的足夠精確值,要求四捨五入到小數點後100位。
小數點後3位的值爲:0.618
小數點後4位的值爲:0.6180
小數點後5位的值爲:0.61803
小數點後7位的值爲:0.6180340
(注意尾部的0,不能忽略)
你的任務是:寫出精確到小數點後100位精度的黃金分割值。
注意:尾數的四捨五入! 尾數是0也要保留!
顯然答案是一個小數,其小數點後有100位數字,請經過瀏覽器直接提交該數字。
注意:不要提交解答過程,或其它輔助說明類的內容。
思路:咱們能夠按照上面的那個公式先寫幾項:1/2,2/3,3/5,5/8,8/13……能夠看出其實就是相鄰兩項斐波那契數相除。以後要輸出小數點後100位,這就須要一點技巧了,參考:https://blog.csdn.net/milkcu/article/details/9103701
答案:
0.6180339887498948481971959525508621220510663574518538453723187601229582821971784348083863296133320592
原文:https://blog.csdn.net/ryo_218/article/details/79703751
代碼填空題:
5.
題目標題:前綴判斷
以下的代碼判斷 needle_start指向的串是否爲haystack_start指向的串的前綴,如不是,則返回NULL。
好比:"abcd1234" 就包含了 "abc" 爲前綴
char* prefix(char* haystack_start, char* needle_start) { char* haystack = haystack_start; char* needle = needle_start; while(*haystack && *needle){ if(______________________________) return NULL; //填空位置 } if(*needle) return NULL; return haystack_start; }
請分析代碼邏輯,並推測劃線處的代碼,經過網頁提交。
注意:僅把缺乏的代碼做爲答案,千萬不要填寫多餘的代碼、符號或說明文字!!
判斷前綴,其實就是比較一下字符串。
while(*haystack && *needle){
if(______________________________) return NULL; //填空位置
}
就是,2個都存在的狀況下,*a是a的首地址,因此咱們要比較的時候須要:
*(haystack++) != *(needle++) 時, 返回false
因此,答案就是*(haystack++) != *(needle++)。
6.
標題:三部排序
通常的排序有許多經典算法,如快速排序、希爾排序等。
但實際應用時,常常會或多或少有一些特殊的要求。咱們不必套用那些經典算法,能夠根據實際狀況創建更好的解法。
好比,對一個整型數組中的數字進行分類排序:
使得負數都靠左端,正數都靠右端,0在中部。注意問題的特色是:負數區域和正數區域內並不要求有序。能夠利用這個特色經過1次線性掃描就結束戰鬥!!
如下的程序實現了該目標。
其中x指向待排序的整型數組,len是數組的長度。
void sort3p(int* x, int len) { int p = 0; int left = 0; int right = len-1; while(p<=right){ if(x[p]<0){ int t = x[left]; x[left] = x[p]; x[p] = t; left++; p++; } else if(x[p]>0){ int t = x[right]; x[right] = x[p]; x[p] = t; right--; } else{ __________________________; //填空位置 } } }
若是給定數組:
25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0
則排序後爲:
-3,-2,-16,-5,0,0,0,21,19,33,25,16,18,25
請分析代碼邏輯,並推測劃線處的代碼,經過網頁提交
注意:僅把缺乏的代碼做爲答案,千萬不要填寫多餘的代碼、符號或說明文字!!
思路:
這裏描述了一個排序算法的思想,就是分紅-1,0,1三個部分,
if(x[p]<0){ int t = x[left]; x[left] = x[p]; x[p] = t; left++; p++; }
這個部分就是交換一下x[p]和x[left]數組的值,使x[left] < 0,同時向右移動p和left。
else if(x[p]>0){ int t = x[right]; x[right] = x[p]; x[p] = t; right--; }
這個就是一樣交換一下x[p] 和 x[right]的值,同時使向左移動right, p因爲處因而0仍是-1仍是1的三種狀態中,因此不用管。
因此
當x[p] == 0的時候,咱們知道,這個時候須要把P右移動,可是不須要改變數組的值,因此答案就是
p++。
7.
標題:錯誤票據
某涉密單位下發了某種票據,並要在年終所有收回。
每張票據有惟一的ID號。整年全部票據的ID號是連續的,但ID的開始數碼是隨機選定的。
由於工做人員疏忽,在錄入ID號的時候發生了一處錯誤,形成了某個ID斷號,另一個ID重號。
你的任務是經過編程,找出斷號的ID和重號的ID。
假設斷號不可能發生在最大和最小號。
要求程序首先輸入一個整數N(N<100)表示後面數據行數。接着讀入N行數據。
每行數據長度不等,是用空格分開的若干個(不大於100個)正整數(不大於100000)
每一個整數表明一個ID號。
要求程序輸出1行,含兩個整數m n,用空格分隔。
其中,m表示斷號ID,n表示重號ID
例如:
用戶輸入:
2
5 6 8 11 9
10 12 9
則程序輸出:
7 9
再例如:
用戶輸入:
6
164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196
172 189 127 107 112 192 103 131 133 169 158
128 102 110 148 139 157 140 195 197
185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190
149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188
113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119
則程序輸出:
105 120
資源約定:
峯值內存消耗 < 64M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要多此一舉地打印相似:「請您輸入...」 的多餘內容。
全部代碼放在同一個源文件中,調試經過後,拷貝提交該源碼。
注意: main函數須要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操做系統的特殊函數。
注意: 全部依賴的函數必須明確地在源文件中 #include <xxx>, 不能經過工程設置而省略經常使用頭文件。
提交時,注意選擇所指望的編譯器類型。
思路:
這道題的難點不是排序,而是字符轉換
這裏用到了了2個函數:
1.strtok: 這個函數的用處是切割字符串,注意,當strtok()在參數s的字符串中發現參數delim中包含的分割字符時,則會將該字符改成\0 字符。在第一次調用時,strtok()必需給予參數s字符串,日後的調用則將參數s設置成NULL。每次調用成功則返回指向被分割出片斷的指針。
具體的話這兩個博客寫的很明確:
http://www.javashuo.com/article/p-hwueereb-eb.html
http://www.javashuo.com/article/p-omfnspzp-gh.html
2.atoi()函數,頭文件是stdilb.h。這個函數的用處是字符串轉換成整型數。
下面是AC代碼:
#include <iostream> #include <cstdio> #include <string.h> #include <stdlib.h> #include <algorithm> using namespace std; const int MX = 100000+10; char s[MX*(100+10)]; int a[MX]; int main() { int duan, chong; duan = 0; chong = 0; int k = 0; int n; scanf("%d", &n); getchar(); //scanf 和 cin 結束會有\n須要去掉。 for(int i = 0; i < n; ++i) { gets(s); char *p; p = strtok(s, " "); a[k++] = atoi(p); while(p) { p = strtok(NULL, " "); if(p) a[k++] = atoi(p); //無p,這個時候是\n,讀入會返回0 } } sort(a, a+k); for(int i = 1; i < k-1; ++i) { //printf("%d\n", a[i]); if(a[i-1]+1 != a[i]) { if(a[i-1] == a[i]) chong = a[i]; else if(a[i-1]+1 == a[i]-1) duan = a[i]-1; } if(duan != 0 && chong != 0) break; } printf("%d %d\n", duan, chong); }
8.
題目標題:翻硬幣
小明正在玩一個「翻硬幣」的遊戲。
桌上放着排成一排的若干硬幣。咱們用 * 表示正面,用 o 表示反面(是小寫字母,不是零)。
好比,可能情形是:**oo***oooo
若是同時翻轉左邊的兩個硬幣,則變爲:oooo***oooo
如今小明的問題是:若是已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬幣,那麼對特定的局面,最少要翻動多少次呢?
咱們約定:把翻動相鄰的兩個硬幣叫作一步操做,那麼要求:
程序輸入:
兩行等長的字符串,分別表示初始狀態和要達到的目標狀態。每行的長度<1000
程序輸出:
一個整數,表示最小操做步數
例如:
用戶輸入:
**********
o****o****
程序應該輸出:
5
再例如:
用戶輸入:
*o**o***o***
*o***o**o***
程序應該輸出:
1
資源約定:
峯值內存消耗 < 64M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要多此一舉地打印相似:「請您輸入...」 的多餘內容。
全部代碼放在同一個源文件中,調試經過後,拷貝提交該源碼。
注意: main函數須要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操做系統的特殊函數。
注意: 全部依賴的函數必須明確地在源文件中 #include <xxx>, 不能經過工程設置而省略經常使用頭文件。
提交時,注意選擇所指望的編譯器類型。
思路:
這道題是道貪心題目,比較簡單,分析規律能夠發現,每一個不一樣的狀況之間須要翻轉的次數爲 n-m+1(用下標來看就是 endi - starti)
下面是AC代碼:
#include <iostream> #include <cstdio> #include <string.h> using namespace std; const int MX = 1000+10; char a[MX], b[MX]; int c[MX]; int main() { int ans = 0; scanf("%s%s", a, b); int n = strlen(a); for(int i = 0; i < n; ++i) c[i] = a[i]==b[i] ? 1:0; int flag = -1; for(int i = 0; i < n; ++i) { if(c[i] == 0) { if(flag == -1) flag = i; else { ans += (i-flag); flag = -1; } } } printf("%d\n", ans); }
標題:連號區間數
小明這些天一直在思考這樣一個奇怪而有趣的問題:
在1~N的某個全排列中有多少個連號區間呢?這裏所說的連號區間的定義是:
若是區間[L, R] 裏的全部元素(即此排列的第L個到第R個元素)遞增排序後能獲得一個長度爲R-L+1的「連續」數列,則稱這個區間連號區間。
當N很小的時候,小明能夠很快地算出答案,可是當N變大的時候,問題就不是那麼簡單了,如今小明須要你的幫助。
輸入格式:
第一行是一個正整數N (1 <= N <= 50000), 表示全排列的規模。
第二行是N個不一樣的數字Pi(1 <= Pi <= N), 表示這N個數字的某一全排列。
輸出格式:
輸出一個整數,表示不一樣連號區間的數目。
示例:
用戶輸入:
4
3 2 4 1
程序應輸出:
7
用戶輸入:
5
3 4 2 5 1
程序應輸出:
9
解釋:
第一個用例中,有7個連號區間分別是:[1,1], [1,2], [1,3], [1,4], [2,2], [3,3], [4,4]
第二個用例中,有9個連號區間分別是:[1,1], [1,2], [1,3], [1,4], [1,5], [2,2], [3,3], [4,4], [5,5]
資源約定:
峯值內存消耗 < 64M
CPU消耗 < 5000ms
請嚴格按要求輸出,不要多此一舉地打印相似:「請您輸入...」 的多餘內容。
全部代碼放在同一個源文件中,調試經過後,拷貝提交該源碼。
注意: main函數須要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操做系統的特殊函數。
注意: 全部依賴的函數必須明確地在源文件中 #include <xxx>, 不能經過工程設置而省略經常使用頭文件。
提交時,注意選擇所指望的編譯器類型。
題意,
這道題讀懂題意了就很簡單。可是,特別繞。題意就是給定你一個區間,這個區間的長度爲R-L+1。要求其連續遞增,就是加一遞增。
因而枚舉全部的區間,找到區間最大值與最小值的差,若是等於下標差,就符合條件。
下面是AC代碼:
#include <iostream> #include <cstdio> using namespace std; const int MX = 50000+10; int a[MX]; int main() { int ans = 0; int n; scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i <= n; ++i) { int mx = 1; int mn = n; for(int j = i; j <= n; ++j) { if(a[j] < mn) mn = a[j]; if(a[j] > mx) mx = a[j]; if(mx-mn == j-i) ans++; } } printf("%d\n", ans); }
若有疑問,歡迎評論指出!