2017牛客網校招模擬第三場筆試編程題
題目來源:https://www.nowcoder.com/test/5217106/summary
1.變換次數
牛牛想對一個數做若干次變換,直到這個數只剩下一位數字。變換的規則是:將這個數變成 所有位數上的數字的乘積。比如285經過一次變換后轉化成2*8*5=80.
問題是,要做多少次變換,使得這個數變成個位數。
輸入描述:
輸入一個整數。小於等於2,000,000,000。
輸出描述:
輸出一個整數,表示變換次數。
輸入例子:
285
輸出例子:
2
分析:
直接暴力計算即可。
1 #include<iostream>
2 using namespace std; 3 int main() 4 { 5 int num, count, tmp; 6 count = 0; 7 cin >> num; 8 while (num > 9) 9 { 10 tmp = 1; 11 for (; num; num = num / 10) 12 { 13 tmp = tmp*(num % 10); 14 } 15 num = tmp; 16 count++; 17 } 18 cout << count << endl; 19 return 0; 20 }
2. 神奇數
給出一個區間[a, b],計算區間內“神奇數”的個數。
神奇數的定義:存在不同位置的兩個數位,組成一個兩位數(且不含前導0),且這個兩位數為質數。
比如:153,可以使用數字3和數字1組成13,13是質數,滿足神奇數。同樣153可以找到31和53也為質數,只要找到一個質數即滿足神奇數。
輸入描述:
輸入為兩個整數a和b,代表[a, b]區間 (1 ≤ a ≤ b ≤ 10000)。
輸出描述:
輸出為一個整數,表示區間內滿足條件的整數個數
輸入例子:
11 20
輸出例子:
6
分析:
對區間內的數進行枚舉,然后按照題目要求的性質進行判斷即可。
1 #include<iostream>
2 using namespace std; 3 bool isprime(int n) //判斷是否為質數
4 { 5 for (int i = 2; i * i <= n; i++) 6 { 7 if (n % i == 0) 8 return false; 9 } 10 return true; 11 } 12
13 bool MagicNum(int m) //判斷是否為神奇數
14 { 15 int cnt[10]; 16 memset(cnt, 0, sizeof(cnt)); 17 while (m) 18 { 19 cnt[m % 10]++; 20 m /= 10; 21 } 22 for (int i = 1; i < 10; i++) 23 { 24 for (int j = 1; j < 10; j++) 25 { 26 if (i != j && cnt[i] && cnt[j]) 27 { 28 if (isprime(i * 10 + j)) 29 return true; 30 } 31 else if (i == j && cnt[i] >= 2) 32 { 33 if (isprime(i * 10 + j)) 34 return true; 35 } 36 } 37 } 38 return false; 39 } 40
41 int main() 42 { 43 int a, b ,count; 44 count = 0; 45 cin >> a >> b; 46 for (int i = a; i <= b; i++) //對區間的數進行枚舉
47 { 48 if (MagicNum(i)) //調用函數,進行判斷,函數返回true或者false
49 count++; 50 } 51 cout << count << endl; //輸出結果
52 return 0; 53 }
3. 添加字符
牛牛手里有一個字符串A,羊羊的手里有一個字符串B,B的長度大於等於A,所以牛牛想把A串變得和B串一樣長,這樣羊羊就願意和牛牛一起玩了。
而且A的長度增加到和B串一樣長的時候,對應的每一位相等的越多,羊羊就越喜歡。比如"abc"和"abd"對應相等的位數為2,為前兩位。
牛牛可以在A的開頭或者結尾添加任意字符,使得長度和B一樣。現在問牛牛對A串添加完字符之后,不相等的位數最少有多少位?
輸入描述:
第一行為字符串A,第二行為字符串B,A的場地小於等於B的長度,B的長度小於等於50.字符均為小寫字母。
輸出描述:
輸出一個整數表示A串添加完字符之后,不相等的位數最少有多少位?
輸入例子:
abe
cabc
輸出例子:
1
分析:
情況分為兩種:1.A的長度小於B的長度 2.A的長度等於B的長度
當小於時,就枚舉B串的一個偏移量,然后枚舉維護最小的不相等的位數。
當等於時,就直接對比就好了。
1 #include<iostream>
2 #include<string>
3 using namespace std; 4
5 int main() 6 { 7 string a, b; 8 cin >> a >> b; 9 int aLength = a.size(), bLength = b.size(); 10 if (aLength < bLength) 11 { 12 int ans = 1e9; 13 for (int i = 0; i + aLength <= bLength; i++) 14 { 15 int cnt = 0; 16 for (int j = 0; j < aLength; j++) 17 { 18 if (a[j] != b[i + j]) 19 cnt++; 20 } 21 if (cnt < ans) 22 { 23 ans = cnt; 24 } 25 } 26 cout << ans << endl; 27 return 0; 28 } 29 else { 30 int cnt = 0; 31 for (int j = 0; j < aLength; j++) 32 { 33 if (a[j] != b[j]) 34 ++cnt; 35 } 36 cout << cnt << endl; 37 } 38 return 0; 39
40 }
4. 數組變換
牛牛有一個數組,里面的數可能不相等,現在他想把數組變為:所有的數都相等。問是否可行。
牛牛可以進行的操作是:將數組中的任意一個數改為這個數的兩倍。
這個操作的使用次數不限,也可以不使用,並且可以對同一個位置使用多次。
輸入描述:
輸入一個正整數N (N <= 50)
接下來一行輸入N個正整數,每個數均小於等於1e9.
輸出描述:
假如經過若干次操作可以使得N個數都相等,那么輸出"YES", 否則輸出"NO"
輸入例子:
2
1 2
輸出例子:
YES
分析:
把數組每一個元素都除以2,直到它為奇數。如果此時數組每個元素都一樣,滿足條件,輸出YES
1 #include<iostream>
2 #include<string>
3 using namespace std; 4
5 int num[55]; 6 int main() 7 { 8 int n; 9 cin >> n; 10 for (int i = 0; i < n; i++) 11 cin >> num[i]; 12 string res = "YES"; 13 for (int i = 0; i < n; i++) 14 { 15 while (!(num[i] & 1)) 16 num[i] >>= 1; 17 } 18 for (int i = 1; i < n; i++) 19 { 20 if (num[i] != num[0]) 21 res = "NO"; 22 } 23 cout << res << endl; 24 return 0; 25 }
5. 排序子序列
牛牛定義排序子序列為一個數組中一段連續的子序列,並且這段子序列是非遞增或者非遞減排序的。牛牛有一個長度為n的整數數組A,他現在有一個任務是把數組A分為若干段排序子序列,牛牛想知道他最少可以把這個數組分為幾段排序子序列.
如樣例所示,牛牛可以把數組A划分為[1,2,3]和[2,2,1]兩個排序子序列,至少需要划分為2個排序子序列,所以輸出2
輸入描述:
輸入的第一行為一個正整數n(1 ≤ n ≤ 10^5)
第二行包括n個整數A_i(1 ≤ A_i ≤ 10^9),表示數組A的每個數字。
輸出描述:
輸出一個整數表示牛牛可以將A最少划分為多少段排序子序列
輸入例子:
6
1 2 3 2 2 1
輸出例子:
2
分析:
考慮序列A_1, A_2, . . . , A_i是一個單調的序列.顯然如果對於j < i把序列分為A_1, A_2. . . A_j 和 A_j+1, A_j+2, . . . , A_i 兩個部分不會使問題變得更優.
於是我們可以貪心的去重復下面過程: 1、 從序列中找出最長的單調連續子序列 2、 刪除找出的最長的單調連續子序列
這里的單調序列包括非遞增和非遞減,而判斷子序列是否單調的時候,注意處理等於的情況。
1 #include<iostream>
2 #include<vector>
3 using namespace std; 4
5 int main() 6 { 7 int n; 8 cin >> n; 9 vector <int> A; 10 int ans = 1; 11 for (int i = 0; i < n; ++i) 12 { 13 int x; 14 cin >> x; 15 if (A.size() <= 1) 16 A.push_back(x); 17 else
18 { 19 if (A[0] <= A.back() && A.back() <= x) 20 A.push_back(x); 21 else if (A[0] >= A.back() && A.back() >= x) 22 A.push_back(x); 23 else
24 { 25 ans++; 26 A.clear(); 27 A.push_back(x); 28 } 29 } 30 } 31 cout << ans << endl; 32 return 0; 33 }
6. 組隊競賽
牛牛舉辦了一次編程比賽,參加比賽的有3*n個選手,每個選手都有一個水平值a_i.現在要將這些選手進行組隊,一共組成n個隊伍,即每個隊伍3人.牛牛發現隊伍的水平值等於該隊伍隊員中第二高水平值。
例如:
一個隊伍三個隊員的水平值分別是3,3,3.那么隊伍的水平值是3
一個隊伍三個隊員的水平值分別是3,2,3.那么隊伍的水平值是3
一個隊伍三個隊員的水平值分別是1,5,2.那么隊伍的水平值是2
為了讓比賽更有看點,牛牛想安排隊伍使所有隊伍的水平值總和最大。
如樣例所示:
如果牛牛把6個隊員划分到兩個隊伍
如果方案為:
team1:{1,2,5}, team2:{5,5,8}, 這時候水平值總和為7.
而如果方案為:
team1:{2,5,8}, team2:{1,5,5}, 這時候水平值總和為10.
沒有比總和為10更大的方案,所以輸出10.
輸入描述:
輸入的第一行為一個正整數n(1 ≤ n ≤ 10^5)
第二行包括3*n個整數a_i(1 ≤ a_i ≤ 10^9),表示每個參賽選手的水平值.
輸出描述:
輸出一個整數表示所有隊伍的水平值總和最大值.
輸入例子:
2
5 2 8 5 1 5
輸出例子:
10
分析:
對於所有參賽隊員,我們把他們的水平值進行逆序排序,然后逐一挨着安排每個隊伍,然后計算出隊伍水平值總和,即為所求。
1 #include<iostream>
2 #include<algorithm>
3
4 using namespace std; 5
6 const int maxn = 300100; 7 int a[maxn]; 8
9 int main() 10 { 11 int n; 12 cin >> n; 13 for (int i = 0; i < 3 * n; i++) 14 cin >> a[i]; 15 sort(a, a + 3 * n); 16 long long ans = 0; 17 for (int i = 0; i < n; i++) 18 ans += a[n + 2 * i]; 19 printf("%lld\n", ans); 20 return 0; 21 }
7. 牛牛的數列
牛牛現在有一個n個數組成的數列,牛牛現在想取一個連續的子序列,並且這個子序列還必須得滿足:最多只改變一個數,就可以使得這個連續的子序列是一個嚴格上升的子序列,牛牛想知道這個連續子序列最長的長度是多少。
輸入描述:
輸入包括兩行,第一行包括一個整數n(1 ≤ n ≤ 10^5),即數列的長度;
第二行n個整數a_i, 表示數列中的每個數(1 ≤ a_i ≤ 10^9),以空格分割。
輸出描述:
輸出一個整數,表示最長的長度。
輸入例子:
6
7 2 3 1 5 6
輸出例子:
5
分析:
正着枚舉記錄一下當前位置的連續上升子序列長度,倒着也做一遍。
最后枚舉一個連接點即可。
1 #include <iostream>
2 #include<algorithm>
3 using namespace std; 4
5 const int maxn = 100000 + 5; 6 const int INF = 0x3f3f3f3f; 7
8 int a[maxn], n; 9 int pre[maxn], suf[maxn]; 10 int main() { 11 cin >> n; 12 for (int i = 1; i <= n; i++) 13 scanf_s("%d", a + i); 14 a[0] = INF, a[n + 1] = INF; 15 for (int i = 1; i <= n; i++) 16 pre[i] = a[i - 1] < a[i] ? pre[i - 1] + 1 : 1; 17 for (int i = n; i >= 1; i--) 18 suf[i] = a[i] < a[i + 1] ? suf[i + 1] + 1 : 1; 19 int ans = 1; 20 for (int i = 1; i <= n; i++) 21 { 22 ans = max(ans, pre[i - 1] + 1); 23 ans = max(ans, suf[i + 1] + 1); 24 if (a[i + 1] - a[i - 1] >= 2) 25 ans = max(ans, pre[i - 1] + suf[i + 1] + 1); 26 } 27 printf("%d\n", ans); 28 return 0; 29 }
