vmware筆試題目


http://discuss.acmcoder.com/topic/58db8e2ebb0f44ba0e94e670

上面是完整的題目,下面一下我自己的想法。

http://discuss.acmcoder.com/topic/58db8e2ebb0f44ba0e94e670

官方題解。

這次做的比較菜,就做出來第二題,1和3都沒搞出來。

1. 第一題,首先知道數一個數階乘末尾0的個數,由於5*2 = 10,5比2多,所以就變成數因子5的個數,5的數法,需要找規律,首先每五個數有一個因子5,然后接下來壓縮后,每5個數,還有一個5,不斷的遞歸調用,即可。同理,數其他的質因子都是這樣吧。

我做的時候,老是以為有什么規律,默認為就是數學題么,肯定有規律的,然后沒接出來。

有了快速數5的個數的方法以后,那么解法就顯而易見了,就是二分。而且題目,也提醒單調的性質,就差直接提醒你用二分了,然后就是對可能的答案進行二分,多了往左走,少了往右走。很容易分析最大可能的答案是最大的數乘以5.然后二分。

總結出一個套路:有單調的性質,或者有非遞減的性質之類的,立馬要想到二分,有些二分可能不明顯,如對答案二分等,需要仔細分析。同時,注意二分的幾種寫法,滿足要求最小的,滿足要求最大的,或者唯一的,寫法都不太一樣,注意。

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const ll inf = 5e8;
 5 
 6 ll work(ll t) {
 7     ll res = 0;
 8     while(t > 1) {
 9         res += t / 5;
10         t /= 5;
11     }
12     return res;
13 }
14 void solve() {
15     int x;
16     for (x = 1; x <= 50; x++) {
17         ll left = 5, right = inf;
18         while(left < right) {
19             ll mid = (left + right) / 2;
20             ll t = work(mid);
21             if(t < x) left = mid + 1;
22             else right = mid;
23         }
24         if(work(left) == x) cout << left << endl;
25         else cout << -1 << endl;
26     }
27 }
28 
29 int main() {
30     freopen("test.in", "r", stdin);
31     freopen("test.out", "w", stdout);
32     ios::sync_with_stdio(0);
33     cin.tie(0); cout.tie(0);
34     solve();
35     return 0;
36 }
View Code

2. 第二題,顯然是一棵樹,然后固定樹的層次結構,對每一個節點,需要找到兒子里面的最長路徑,以及該節點外的最長路徑,發現不好計算,然后轉化為依次切割每一條邊,分別這個邊兩邊的最長路徑。看答案,我是真的把邊刪掉,其實只要簡單設置根節點的父節點為相鄰節點即可,真是個好方法。然后這個題數據范圍很小,應該能跑出來,每次都是O(n)的,所以很容易的就ac了。

 1 /*
 2 ID: y1197771
 3 PROG: test
 4 LANG: C++
 5 */
 6 #include<bits/stdc++.h>
 7 #define pb push_back
 8 #define FOR(i, n) for (int i = 0; i < (int)n; ++i)
 9 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
10 typedef long long ll;
11 using namespace std;
12 typedef pair<int, int> pii;
13 const int maxn = 2e2 + 10;
14 int e[maxn][maxn];
15 int n;
16 vector<pii> a;
17 int ans;
18 int work(int u, int p) {
19     int x, y;
20     x = y = 0;
21     for (int i = 1; i <= n; i++) {
22         if(e[u][i] && i != p) {
23             int t = work(i, u);
24             if(t > y) y = t;
25             if(y > x) swap(x, y);
26         }
27     }
28     ans = max(ans, x + y + 1);
29     return x + 1;
30 }
31 void solve() {
32     while(cin >> n) {
33         memset(e, 0, sizeof e);
34         int x, y;
35         a.clear();
36         for (int i = 0; i < n - 1; i++)  {
37             cin >> x >> y;//cout << x << " " << y << endl;
38             e[x][y] = 1;
39             e[y][x] = 1;
40             a.pb({x, y});
41 
42         }
43 
44         int res = 0;
45 
46         for (int i = 0; i < n - 1; i++) {
47             x = a[i].first, y = a[i].second;
48             e[x][y] = e[y][x] = 0;
49             int t1, t2;
50             t1 = t2 = 0;
51             ans = 0;
52             work(x, 0);
53             t1 = max(0, ans - 1);
54             ans = 0;
55             work(y, 0);
56             t2 = max(0, ans - 1);
57             res = max(res, t1 * t2);
58             e[x][y] = e[y][x] = 1;
59         }
60         cout << res << endl;
61     }
62 }
63 int main() {
64     freopen("test.in", "r", stdin);
65     //freopen("test.out", "w", stdout);
66     ios::sync_with_stdio(0);
67     cin.tie(0); cout.tie(0);
68     solve();
69     return 0;
70 }
View Code

3. 第三題,讀完題意,沒啥想法,我的想法是對每一個區間進行求解,每個區間必須是匹配的,也就是完整的,然后第一個位置就是‘(’,然后一次枚舉‘)’可以放的位置,進行遞歸求解,復雜度太高。直接tle。

沒想法,只好看題解答案。

居然是轉化成1,-1的形式進行處理,太巧秒了!(我就想到上次有一個01的序列,求最長的區間,這個區間滿足0和1的個數相等,也是處理成-1和1的形式,真是夠巧妙的。)處理成1,-1的形式,那么括號匹配的情況就很顯然了,就是前面和為0,而且合法的情況必然是前面的和大於等於0的,這個也很關鍵,下面考慮怎么縮減問題規模,也就是怎么轉移(通常的dp套路,縮減問題規模,轉化為規模較小的子問題,而分出來的那一小部分很好計算)。然后就是第k個位置,可能的合法的情況就是0-k,0代表前面完全匹配,k代表前面的都是左括號,這樣,前面就不會出現右括號不匹配的情況。

特別注意n*=2,然后考慮還會有一些非法的情況出現,比如偶數位置上,是不可能達到0的,設置這些狀態為一個很小的數,使得不干擾最后的結果。

真是個好題!

 1 /*
 2 ID: y1197771
 3 PROG: test
 4 LANG: C++
 5 */
 6 #include<bits/stdc++.h>
 7 #define pb push_back
 8 #define FOR(i, n) for (int i = 0; i < (int)n; ++i)
 9 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
10 typedef long long ll;
11 using namespace std;
12 typedef pair<int, int> pii;
13 const int maxn = 1e3 + 10;
14 const int inf = -1e9;
15 int dp[2010][2010];
16 int n;
17 int a1[2010], a2[2010];
18 void solve() {
19     cin >> n;
20     for (int i = 1; i <= 2 * n; i++) {
21         cin >> a1[i];
22     }
23     for (int i = 1; i <= 2 * n; i++) {
24         cin >> a2[i];
25     }
26     for (int i = 1; i <= n * 2; i++)
27         dp[0][i] = inf;
28     for (int i = 1; i <= n * 2; i++) {
29         for (int j = 0; j <= i; j++) {
30             if(j == 0) {
31                 dp[i][j] = dp[i - 1][j + 1] + a2[i];
32             } else {
33                 dp[i][j] = max(dp[i - 1][j + 1] + a2[i], dp[i - 1][j - 1] + a1[i]);
34             }
35         }
36     }
37     cout << dp[n * 2][0] << endl;
38 }
39 int main() {
40     freopen("test.in", "r", stdin);
41     //freopen("test.out", "w", stdout);
42     ios::sync_with_stdio(0);
43     cin.tie(0); cout.tie(0);
44     solve();
45     return 0;
46 }
View Code

做完題目,只有多總結,分析原因,尤其是自己當初做的時候是怎么想的,有沒有計算復雜度,考慮可行性, 不行的話,有沒有pass掉, 然后為什么沒有想出題解的這樣的方式,這才是最重要的,這樣提高才是最快的,否則,跟沒有做一樣!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM