第一題
網友年齡
某君新認識一網友。
當問及年齡時,他的網友說:
“我的年齡是個2位數,我比兒子大27歲,
如果把我的年齡的兩位數字交換位置,剛好就是我兒子的年齡”
請你計算:網友的年齡一共有多少種可能情況?
提示:30歲就是其中一種可能哦.
請填寫表示可能情況的種數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
【思路】
寫一個循環即可解決問題。
答案:7
#include <iostream>
using namespace std;
int main() {
int rec = 0, note;
for (int i = 1; i <= 99; i++) {
note = (i%10)*10 + i/10;
if (i - note == 27)
rec++;
}
cout << rec << endl;
return 0;
}
第二題
生日蠟燭
某君從某年開始每年都舉辦一次生日party,並且每次都要吹熄與年齡相同根數的蠟燭。
現在算起來,他一共吹熄了236根蠟燭。
請問,他從多少歲開始過生日party的?
請填寫他開始過生日party的年齡數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
【思路】
由於是填空題,用了兩個簡單的循環。
答案:26
#include <iostream>
using namespace std;
int main() {
int rec, t;
for (int i = 1; i <= 100; i++) {
rec = 0;
t = i;
while (rec < 236) {
rec += t;
t++;
}
if (rec == 236) {
cout << i << endl;
break;
}
}
return 0;
}
第三題
方格填數
如下的10個格子
填入0~9的數字。要求:連續的兩個數字不能相鄰。
(左右、上下、對角都算相鄰)
一共有多少種可能的填數方案?
請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
【思路】
把所有的情況枚舉一遍,把不連續的要求全部列出來,同時滿足則找到一種方案。
答案:1580
#include <iostream>
#include <string>
#include <cstdlib>
#include <algorithm>
using namespace std;
bool cn(string s) {
if (abs(s[0]-s[1]) != 1 && abs(s[0]-s[3]) != 1 && abs(s[0]-s[4]) != 1 && abs(s[0]-s[5]) != 1 &&
abs(s[1]-s[2]) != 1 && abs(s[1]-s[4]) != 1 && abs(s[1]-s[5]) != 1 && abs(s[1]-s[6]) != 1 &&
abs(s[2]-s[5]) != 1 && abs(s[2]-s[6]) != 1 &&
abs(s[3]-s[4]) != 1 && abs(s[3]-s[7]) != 1 && abs(s[3]-s[8]) != 1 &&
abs(s[4]-s[5]) != 1 && abs(s[4]-s[7]) != 1 && abs(s[4]-s[8]) != 1 && abs(s[4]-s[9]) != 1 &&
abs(s[5]-s[6]) != 1 && abs(s[5]-s[8]) != 1 && abs(s[5]-s[9]) != 1 &&
abs(s[6]-s[9]) != 1 && abs(s[7]-s[8]) != 1 && abs(s[8]-s[9]) != 1)
return true;
else
return false;
}
int main() {
string s = "0123456789";
int rec = 0;
do {
if (cn(s)) rec++;
} while (next_permutation(s.begin(), s.end()));
cout << rec << endl;
return 0;
}
第四題
快速排序
排序在各種場合經常被用到。
快速排序是十分常用的高效率的算法。
其思想是:先選一個“標尺”,
用它把整個隊列過一遍篩子,
以保證:其左邊的元素都不大於它,其右邊的元素都不小於它。
這樣,排序問題就被分割爲兩個子區間。
再分別對子區間排序就可以了。
下面的代碼是一種實現,請分析並填寫劃線部分缺少的代碼。
#include <stdio.h>
void swap(int a[], int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
int partition(int a[], int p, int r)
{
int i = p;
int j = r + 1;
int x = a[p];
while(1){
while(i<r && a[++i]<x);
while(a[--j]>x);
if(i>=j) break;
swap(a,i,j);
}
________________________;
return j;
}
void quicksort(int a[], int p, int r)
{
if(p<r){
int q = partition(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
int main()
{
int i;
int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
int N = 12;
quicksort(a, 0, N-1);
for(i=0; i<N; i++) printf("%d ", a[i]);
printf("\n");
return 0;
}
注意:只填寫缺少的內容,不要書寫任何題面已有代碼或說明性文字。
【思路】
瞭解快排的同學應該清楚,最終的目標是將"標尺"放到適當的位置,由於這個程序選擇的"標尺"在排序的左邊,所以應該拿"標尺"與小於"標尺"的最右邊的元素交換。
答案:swqp(a,p,j)
第五題
消除尾一
下面的代碼把一個整數的二進制表示的最右邊的連續的1全部變成0
如果最後一位是0,則原數字保持不變。
如果採用代碼中的測試數據,應該輸出:
00000000000000000000000001100111 00000000000000000000000001100000
00000000000000000000000000001100 00000000000000000000000000001100
請仔細閱讀程序,填寫劃線部分缺少的代碼。
#include <stdio.h>
void f(int x)
{
int i;
for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf(" ");
x = ___________;
for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf("\n");
}
int main()
{
f(103);
f(12);
return 0;
}
注意:只填寫缺少的內容,不要書寫任何題面已有代碼或說明性文字。
【思路】
一個二進制數,加1,末位連續的1全爲0,進位加1,再與原來的數進行與操作,得到結果。
答案:x&(x+1)
第六題
寒假作業
現在小學的數學題目也不是那麼好玩的。
看看這個寒假作業:
□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
每個方塊代表1~13中的某一個數字,但不能重複。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
就算兩種解法。(加法,乘法交換律後算不同的方案)
你一共找到了多少種方案?
請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
【思路】
深搜+剪枝,別人的思路,剪枝剪得很妙,贊一個!(又學到東西了,開心。)
答案:64
#include <iostream>
#include <cstring>
using namespace std;
int visit[13], a[12];
int rec = 0;
void dfs(int t) {
if (t >= 3 && a[0] + a[1] != a[2]) //剪枝
return ;
if (t >= 6 && a[3] - a[4] != a[5])
return ;
if (t >= 9 && a[6] * a[7] != a[8])
return ;
if (t >= 12 && a[9] == a[10] * a[11]) {
rec++;
return ;
}
if (t >= 12)
return;
for (int i = 1; i <= 13; i++) {
if (!visit[i]) {
visit[i] = 1;
a[t] = i;
dfs(t+1);
visit[i] = 0;
}
}
}
int main() {
memset(a, 0, sizeof(a));
memset(visit, 0, sizeof(visit));
dfs(0);
cout << rec << endl;
return 0;
}
第七題
剪郵票
如
有12張連在一起的12生肖的郵票。
現在你要從中剪下5張來,要求必須是連着的。
(僅僅連接一個角不算相連)
比如,
中,粉紅色所示部分就是合格的剪取。
請你計算,一共有多少種不同的剪取方法。
請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
【思路】
參考別人的思路。
1.遍歷所有的方案
2.每個方案利用深搜判斷是否鏈接,鏈接則方案數加一
重點在於深搜的設計。
首先存儲到某個方案,調用深搜,dfs()函數遍歷到某個點,判斷它周圍的四個點是否在方案裏面,如果在方案裏面,且該點未曾被遍歷到,則標記該點被遍歷。
可以利用每個點的數值得到周圍的四個點,但由於4和5不相連,8和9不相連,改變方格的值爲:
1 2 3 4
6 7 8 9
11 12 13 14
這樣,每個點遍歷上下左右的點的距離分別爲{-5,+5,-1,+1}
纖細設計兄弟們去體會下代碼吧。。。我盡力了。
#include <iostream>
#include <cstring>
using namespace std;
const int num = 5;
int a[num], visit[num], t;
int map[] = {1,2,3,4,6,7,8,9,11,12,13,14};
int b[] = {-1, 1, -5, 5};
void dfs(int n) {
for (int i = 0; i < 4; i++) { //嘗試當前點的四個方向
t = a[n] + b[i];
if (t == 5 || t == 10 || t > 14 || t < 1) //t的值不在表格內,遍歷下一個方向
continue;
for (int j = 0; j < 5; j++)
if (!visit[j] && t == a[j]) { //當前點的某一個方向的點在當前方案中
visit[j] = 1;
dfs(j);
}
}
}
int main(){
bool flag;
int rec = 0;
for (int i = 0; i < 12; i++)
for (int j = i + 1; j < 12; j++)
for (int k = j + 1; k < 12; k++)
for (int l = k + 1; l < 12; l++)
for (int n = l + 1; n < 12; n++) {
a[0] = map[i];
a[1] = map[j];
a[2] = map[k];
a[3] = map[l];
a[4] = map[n];
memset(visit, 0, sizeof(visit));
dfs(0);
flag = true;
for (int m = 0; m < num; m++)
if (!visit[m]) {
flag = false;
break;
}
if (flag == true)
rec ++;
}
cout << rec << endl;
return 0;
}
第八題
四平方和
四平方和定理,又稱爲拉格朗日定理:
每個正整數都可以表示爲至多4個正整數的平方和。
如果把0包括進去,就正好可以表示爲4個數的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符號表示乘方的意思)
對於一個給定的正整數,可能存在多種平方和的表示法。
要求你對4個數排序:
0 <= a <= b <= c <= d
並對所有的可能表示法按 a,b,c,d 爲聯合主鍵升序排列,最後輸出第一個表示法
程序輸入爲一個正整數N (N<5000000)
要求輸出4個非負整數,按從小到大排序,中間用空格分開
例如,輸入:
5
則程序應該輸出:
0 0 1 2
再例如,輸入:
12
則程序應該輸出:
0 2 2 2
再例如,輸入:
773535
則程序應該輸出:
1 1 267 838
資源約定:
峯值內存消耗 < 256M
CPU消耗 < 3000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。
所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。
注意: main函數需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。
注意: 所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。
提交時,注意選擇所期望的編譯器類型。
【思路】
暴力破解,枚舉4個數,符合條件結束程序,用三個循環即可,第四個數直接計算出來,降低時間複雜度。
#include <iostream>
#include <cmath>
using namespace std;
const int NUM = 5000000;
int main(){
int num = sqrt(5000000);
int n, d;
bool flag = false;
cin >> n;
for (int a = 0; a <= num; a++)
for (int b = 0; b <= num; b++)
for (int c = 0; c <= num; c++) {
d = sqrt(n - (a * a + b * b + c * c));
if (n == a * a + b * b + c * c + d * d) {
if (c > d) {
int temp = c;
c = d;
d = temp;
}
cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
return 0;
}
}
}
這裏呈上別人的思路。用一個數組存儲所有小於n的數中能被2個數的平方和求得的數。從這些數中找出符合條件的數即可,具體實現看代碼。這種方法有效地減低了時間複雜度,但是需要消耗更多的內存。
#include <iostream>
#include <cmath>
using namespace std;
const int NUM = 5000010;
int map[NUM] = {0};
int n;
void f() {
for (int i = 0; i * i <= n; i++)
for (int j = 0; j * j <= n; j++)
if (i * i + j * j <= n)
map[i * i + j * j] = 1; //這個數可以用兩個數平方求得
}
int main(){
cin >> n;
f();
for (int i = 0; i * i <= n; i++) {
for (int j = 0; j * j <= n; j++) {
if (map[n - i * i - j * j] == 0)
continue;
for (int k = 0; k * k <= n; k++) {
int p = sqrt(n - i * i - j * j - k * k);
if ((i * i + j * j + k * k + p * p) == n) {
cout << i << ' ' << j << ' ' << k << ' ' << p << endl;
return 0;
}
}
}
}
}
第九題
密碼脫落
X星球的考古學家發現了一批古代留下來的密碼。
這些密碼是由A、B、C、D 四種植物的種子串成的序列。
仔細分析發現,這些密碼串當初應該是前後對稱的(也就是我們說的鏡像串)。
由於年代久遠,其中許多種子脫落了,因而可能會失去鏡像的特徵。
你的任務是:
給定一個現在看到的密碼串,計算一下從當初的狀態,它要至少脫落多少個種子,纔可能會變成現在的樣子。
輸入一行,表示現在看到的密碼串(長度不大於1000)
要求輸出一個正整數,表示至少脫落了多少個種子。
例如,輸入:
ABCBA
則程序應該輸出:
0
再例如,輸入:
ABDCDCBABC
則程序應該輸出:
3
資源約定:
峯值內存消耗 < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。
所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。
注意: main函數需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。
注意: 所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。
提交時,注意選擇所期望的編譯器類型。
【思路】
很慚愧還是大神的思路,源博主找不到了,因爲看的博客沒有標明,學習一下。
用的方法還是我們熟悉的深搜,但是我覺得需要在充分了解題目的基礎上,才能知道用這樣的判斷可以得到答案。。。
#include <iostream>
#include <string>
using namespace std;
int num = 100000;
string str;
void dfs(int l, int r, int len) {
if (l >= r)
num = (num < len ? num : len);
else {
if (str[l] == str[r])
dfs(l + 1, r - 1, len);
else {
dfs(l + 1, r, len + 1);
dfs(l, r - 1, len + 1);
}
}
return ;
}
int main(){
cin >> str;
dfs(0, str.size() - 1, 0);
cout << num << endl;
return 0;
}