【360】2019校招筆試編程題合集


u1s1,好難。。兩個小時根本做不完。最后找第三題的bug找到凌晨四點才過。


 

 

試題鏈接:2019校招筆試編程題合集 

 

1、城市修建

題意:有一個城市需要修建,給你N個民居的坐標X,Y,問把這么多民居全都包進城市的話,城市所需最小面積是多少(注意,城市為平行於坐標軸的正方形)

 

題解:記得看題,是正方形!!!。先開始一直沒過以為是長方形來着。。

記錄輸入的最大x,y和最小小x,y。然后相減,比較減出來最大的那個就是所求邊長了。

 

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int inf = 1e9*5;
 5 
 6 
 7 int main(){
 8     int n;
 9     cin>>n;
10     ll x,y;
11     ll x1 = inf,y1 = inf;
12     ll x2 = -inf,y2 = -inf;
13     for(int i = 0 ;i < n;i++){
14         cin>>x>>y;
15         x1 = min(x,x1);
16         y1 = min(y,y1);
17         x2 = max(x,x2);
18         y2 = max(y,y2);
19     }
20 
21     ll width = abs(x2-x1);
22     ll height = abs(y2-y1);
23 
24     ll ans = max(width,height);
25  
26     cout<<ans*ans<<endl;
27 
28     return 0;
29 }
View Code

 

 

2、圈地運動

題意:圈地運動,就是用很多木棍擺在地上組成一個面積大於0的多邊形~

小明喜歡圈地運動,於是他需要去小紅店里面買一些木棍,期望圈出一塊地來。小紅想挑戰一下小明,所以給小明設置了一些障礙。障礙分別是:

1.如果小明要買第i塊木棍的話,他就必須把前i-1塊木棍都買下來。

2.買了的木棍都必須用在圈地運動中。

那么請問小明最少買多少根木棍,才能使得木棍圍成的圖形是個面積大於0多邊形呢?

 

題解:這個本質是判斷多邊形的組成條件。構成m條邊的多邊形的條件,任意的m-1條邊之和必須大於第m條邊。

我們根據這個性質來做判斷,當前最大值的邊是否小於其他邊的和。

 

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int inf = 1e9;
 5 
 6 int main(){
 7     int n;
 8     cin>>n;
 9     int cursum = 0;
10     int maxlen = 0;
11     int x;
12     
13     if(n < 3)   cout<<-1<<endl;
14     else{
15         int cnt = 1;
16         int flag = 0;
17         cin>>x;
18         maxlen = x;
19         for(int i = 1; i < n ;i++){
20             cin>>x;
21             cnt++;
22             if(x > maxlen){
23                 cursum += maxlen;
24                 maxlen = x;
25             }
26             else    cursum += x;
27 
28             if(cursum > maxlen){
29                 flag = 1;
30                 break;
31             }
32             
33         }
34         if(flag)    cout<<cnt<<endl;
35         else    cout<<-1<<endl;
36 
37     }
38 
39 
40     return 0;
41 }
View Code

 

 

3、Bittttttts

題意:現在有q個詢問,每次詢問想問你在[l,r]區間內,k進制表示中,k-1的數量最多的數是哪個數。比如當k=2時,9的二進制就是1001,那么他就有2個1.

 

題解:這題真的想了我好久。。本來准備用線段樹做離線操作。后來發現1e16還是太大了。最后經韜韜點撥,發現可以這樣思考。

[l,r]這個區間我們不需要完全知道k進制以后的所有。

  • 首先需要比較l,r轉化成k進制以后的數。補齊l的位數(因為l位數可能<=r的位數)
  • 然后從高位開始比較l,r每一位,如果當前位不相同,記錄一下
  • 我們就從下一位開始將l的每一位變成k-1。(高位是根據l來判斷的。因為所得數一定要在[l,r])
  • 考慮特殊情況(在下面講解)
  • 轉成十進制輸出

比如:  8進制下 1和100.   1->1   100->144

首先補齊位數,001和144。從高位開始比較。可以得到最大的數是077。再轉成十進制輸出。

不明白的話再舉一個例子:10進制下, 987666666和987566666

987666666

987566666  那么我們轉換的最大k-1的數是 987599999

大概思路就是這樣,里面的細節需要注意,下面就是特殊情況。

1、當r全是k-1時,我們要輸出r。比如10進制下11111 99999 ,此時應該輸出99999

2、當r從和l不等的這個pos這里全是k-1時,輸出r。比如10進制下 1234567 1234999,此時輸出1234999(這個情況想了好久,后面看到討論區大佬給的數據才恍然大悟!!!!!)

具體的看一下代碼,代碼里給了注釋。

 

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int inf = 1e9;
 5 
 6 ll maxnum = 0;
 7 ll ans = 0;
 8 
 9 vector<int> left_num;
10 vector<int> right_num;
11 
12 //判斷右邊是不是全是k-1
13 bool all_r(int k){
14     int len = right_num.size();
15     for(int i = 0 ;i < len;i++){
16         if(right_num[i] != k-1){
17             return false;
18         }
19     }
20     return true;
21 
22 }
23 
24 ll query(int k,ll l, ll r){
25     ll res = r; 
26     while(l){
27         left_num.push_back(l%k);
28         l /= k;
29     }
30     while(r){
31         right_num.push_back(r%k);
32         r /= k;
33     }
34     //全為k-1的情況
35     if(all_r(k)) return res;
36 
37     int len = right_num.size();
38     int len1 = len - left_num.size();
39 
40     while(len1--)   left_num.push_back(0);
41 
42     ll ans=0;
43     int pos = 0;
44     for(int i = len-1 ; i >= 0 ;i--){
45         if(left_num[i] != right_num[i]){
46             pos = i;
47             break;
48         }   
49     }
50     //cout<<pos<<endl;
51 
52     int flag = 1;
53     for(int i = pos ;i >= 0;i--){
54         if(right_num[i] != k-1){
55             flag = 0;
56             break;
57         }
58     }
59     if(flag)    return res;
60     //[len-1,pos]按l
61     for(int i = len-1; i >= pos ;i--)
62         ans = ans*k + left_num[i];
63     
64     //[pos+1,0]按k-1
65     for(int i = pos-1; i >= 0 ;i--)   
66         ans = ans*k + k-1;
67     
68     return ans;
69 }
70 int main(){
71     int q;
72     cin>>q;
73     int k;
74     ll l,r;
75     while(q--){
76         cin>>k>>l>>r;
77         left_num.clear();
78         right_num.clear();
79         cout<<query(k,l,r)<<endl;
80     }
81 
82 
83     return 0;
84 }
View Code

 

 

4、看花

題意:小明有一個花園,花園里面一共有m朵花,對於每一朵花,都是不一樣的,小明用1~m中的一個整數表示每一朵花。

他很喜歡去看這些花,有一天他看了n次,並將n次他看花的種類是什么按照時間順序記錄下來。

記錄用a[i]表示,表示第i次他看了a[i]這朵花。

小紅很好奇,她有Q個問題,問[l,r]的時間內,小明一共看了多少朵不同的花兒,小明因為在忙着欣賞他的花兒,所以想請你幫他回答這些問題。

 

題解:查詢區間內不同數的個數。標准主席樹。。

我就直接上板子了。這里記得用c的輸入輸出否則TLE。討論區好像set暴力可行。。

 

代碼:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 const int maxn = 30010;
  5 const int M = maxn*100;
  6 
  7 int a[maxn];
  8 int T[maxn],lson[M],rson[M];
  9 int c[M];   //保存當前根節點中元素的個數
 10 
 11 int n,m,q,tot;
 12 
 13 //建樹
 14 int build(int l,int r){
 15     int root = tot++;
 16     c[root] = 0;
 17     if(l!=r){
 18         int mid = (l+r)>>1;
 19         lson[root] = build(l,mid);
 20         rson[root] = build(mid+1,r);
 21     }
 22     return root;
 23 }
 24 
 25 int update(int root,int pos,int val){
 26     int newroot = tot++;
 27     int tmp = newroot;
 28     c[newroot] = c[root] + val;
 29     int l = 1,r = n;
 30     while(l < r){
 31         int mid = (l+r)>>1;
 32         if(pos <= mid){
 33             lson[newroot] = tot++;
 34             rson[newroot] = rson[root];
 35             newroot = lson[newroot];    
 36             root = lson[root];
 37             r = mid;
 38         }
 39         else{
 40             rson[newroot] = tot++;
 41             lson[newroot] = lson[root];
 42             newroot = rson[newroot];
 43             root = rson[root];
 44             l = mid+1;
 45         }
 46         c[newroot] = c[root]+val;
 47     }
 48     return tmp;
 49 }
 50 
 51 int query(int root,int pos){
 52     int ret = 0;
 53     int l = 1,r = n;
 54     while(pos < r){
 55         int mid = (l+r)>>1;
 56         if(pos <= mid){
 57             r = mid;
 58             root = lson[root];
 59         }
 60         else{
 61             ret += c[lson[root]];
 62             root = rson[root];
 63             l = mid+1;
 64         }
 65     }
 66     return ret + c[root];
 67 }
 68 
 69 
 70 int main(){
 71     scanf("%d%d",&n,&m);
 72     //cin>>n>>m;
 73     tot = 0;
 74     for(int i = 1;i <= n ;i++){
 75         scanf("%d",&a[i]);
 76         //cin>>a[i];
 77     }
 78     T[n+1] = build(1,n);
 79     map<int,int>mp;
 80     for(int i = n ;i >= 1;i--){
 81         if(mp.find(a[i]) == mp.end()){
 82             T[i] = update(T[i+1],i,1);
 83         }
 84         else{
 85             int tmp = update(T[i+1],mp[a[i]],-1);
 86             T[i] = update(tmp,i,1);
 87         }
 88         mp[a[i]] = i;
 89     }
 90     scanf("%d",&q);
 91     //cin>>q;
 92     while(q--){
 93         int l,r;
 94         scanf("%d%d",&l,&r);
 95         //cin>>l>>r;
 96         printf("%d\n",query(T[l],r));
 97         //cout<<query(T[l],r)<<endl;
 98     }
 99     
100     return 0;
101 }
View Code

 

 

5、Array

題意:小紅有兩個長度為n的排列A和B。每個排列由[1,n]數組成,且里面的數字都是不同的。

現在要找到一個新的序列C,要求這個新序列中任意兩個位置(i,j)滿足:

如果在A數組中C[i]這個數在C[j]的后面,那么在B數組中需要C[i]這個數在C[j]的前面。

請問C序列的長度最長為多少呢?

 

題解:這個題最開始想到是逆序B數組,找AB的LCS。二維DP,明顯TLE(30%)

然后優化成一維DP,還是不行(40%)交完卷以后康康別人的討論得到靈感。

我們用一個map來標記A數組中數字的索引。在B數組的輸入時直接給當前數字的索引。

轉化成尋找最長下降子序列(感嘆一下這個操作真的很巧妙。。)

舉例:A:12435   B:52341

A:  1 2 4 3 5

mp:  0 1 2 3 4

B:    4 1 3 2 0

此時就是找B中最長下降子序列:4 3 2 0得到長度是4。

這里要用O(nlogn)優化過時間的算法。可以自己寫二分,也可以用STL自帶。

 

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn = 1e5+10;
 5 const int inf = 0xfffffff;
 6 int n;
 7 int b[maxn];
 8 int dp[maxn]= {0};
 9  
10 /*
11 int search(int x){
12     int l,r,mid;
13     l = 0;r = n;
14     while(l < r){
15         mid = (l+r)/2;
16         if(b[mid] >= x)  r = mid;
17         else    l = mid+1;
18     }
19  
20     return l;
21 }*/
22  
23  
24 int main(){
25      
26     cin>>n;
27     int x;
28  
29     map<int,int>mp;
30  
31     for(int i = 0; i < n; i++){
32         cin>>x;
33         mp[x] = i;
34     }
35     for(int i = 0; i < n ;i++){
36         cin>>x;
37         b[i] = mp[x];
38     }
39     /*
40     for(int i = 0; i < n ;i++){
41         cout<<b[i]<<" ";
42     }
43     cout<<endl;*/
44  
45     memset(dp,0,sizeof(dp));
46  
47     int ans = 0;
48     dp[0] = b[0];
49  
50     for(int i = 1 ; i < n ;i++){
51         if(b[i] < dp[ans])
52             dp[++ans] = b[i];
53         else
54             //dp[search(b[i])] = b[i];
55             dp[lower_bound(dp, dp+n, b[i], greater <int> ()) - dp] = b[i];
56     } 
57  
58  
59     cout<<ans+1<<endl;
60  
61  
62     return 0;
63 }
View Code

 

 

6、魔法排列

題意:眾所周知,集合{1 2 3 … N}有N!種不同的排列,假設第i個排列為Pi且Pi,j是該排列的第j個數。將N個點放置在x軸上,第i個點的坐標為xi且所有點的坐標兩兩不同。對於每個排列(以Pi為例),可以將其視為對上述N個點的一種遍歷順序,即從第Pi,1個點出發,沿直線距離到達第Pi,2個點,再沿直線距離到達第Pi,3個點,以此類推,最后到達第Pi,N個點,將該路線的總長度定義為L(Pi),那么所有N!種路線的總長度之和是多少,即L(P1)+L(P2)+L(P3)+...+L(PN!)的結果是多少?

 

題解:用STL里next_permutation能過26.67%。當時時間已經不夠了。。。

討論區大佬的題解寫的很詳細。。但是我還是有點不太會推。。等我下午推了我補一下過程。

先給公式。。

$num_k = [k*(N-k) + k*(N-k)]*(N-1)! = 2*k*(N-k)*(N-1)!$

$D_{total} = \sum ^{N-1}_{k = 1} num_k * d_k$

取模一定要記得每一步最好都要取模,不能一下子一起取,會出現溢出的情況。

 

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn = 1e5+10;
 5 const int mod = 1e9+7;
 6 
 7 int num[maxn];
 8 ll ans = 0;
 9 int n;
10 
11 int main(){
12     cin>>n;
13     for(int i = 0; i < n ;i++){
14         cin>>num[i];
15     }
16     ll fac = 1; //n-1的階乘
17     for(int i = 1;i < n ;i++)
18         fac = (fac*i + mod)%mod;
19 
20     ll dis = 0; //表示d
21     ll a;
22 
23     for(ll i = 1; i < n ;i++){
24         dis = (num[i]-num[i-1]) % mod;
25         a = 2*i*(n-i)%mod;
26         a = (a*dis)%mod;
27         ans = (ans+a)%mod;
28     }
29 
30     ans = (ans * fac) % mod;
31 
32     cout<<ans<<endl;
33     return 0;
34 }
View Code

 


免責聲明!

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



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