Nowcoder Girl 參考題解【待寫】


【官方題解】:https://www.nowcoder.com/discuss/65411?toCommentId=1134823

【題目鏈接】:https://www.nowcoder.com/test/question/8fd2b461f3874031a29bdf5aac3c8d51?pid=8527168&tid=12942913

1.

妞妞聽說Nowcoder Girl女生編程挑戰賽要開始了, 但是她沒有足夠的勇氣報名參加, 牛牛為了幫助妞妞,給她准備一台勇氣獲得機。初始的時候妞妞的勇氣值是0, 勇氣獲得機有兩個按鈕:

1、N按鈕: 如果當期擁有的勇氣值為x, 按下之后勇氣值將變為2*x+1,

2、G按鈕: 如果當前擁有的勇氣值為x, 按下之后勇氣值將變為2*x+2,

勇氣值過高也會膨脹,所以妞妞需要將自己的勇氣值恰好變為n, 請你幫助她設計一個勇氣獲得機的按鍵方案使妞妞的勇氣值恰好變為n。

 輸入描述:

輸入包括一行, 包括一個正整數n(1 <= n <= 10^9), 表示妞妞最后需要的勇氣值。

輸出描述:

輸出一行字符串, 每個字符表示該次妞妞選擇按動的按鈕,'N'表示該次按動N按鈕,'G'表示該次按動G按鈕。

輸入例子1:

20

 輸出例子1:

NGNG

【分析】:仔細觀察會發現,每一步的按鍵方案由奇偶性確定,於是分類確定即可; 也可以用用while實現一個遞歸。
【代碼】:
#include <bits/stdc++.h>
 
using namespace std;
 
int n;
stack<char> s;
int main() {
    cin >> n;
    while(n) {
        if(n % 2 == 0) {
            n = (n - 2) / 2;
            s.push('G');
        } else {
            n = (n - 1) / 2;
            s.push('N');
        }
    }
    while(!s.empty()) {
        printf("%c", s.top());
        s.pop();
    }
    printf("\n");
    return 0;
}
O(logn)/分類討論

 

作者:shiqitao
鏈接:https://www.nowcoder.com/discuss/65424?type=0&order=0&pos=6&page=0
來源:牛客網

#include <iostream>
#include <string>
using namespace std;
int main()
{
    int n; cin >> n;
    string result = "";
    while (n != 0) {
        result = (n % 2 ? "N" : "G") + result;
        n = (n - 1) / 2;
    }
    cout << result;
    return 0;
}
遞歸

 


 

妞妞得到一個(1~n)的排列p1, p2, p3,...,pn, 聽村里的老人牛牛說如果讓這個排列變為:

對於所有的1 <= i <= n, 都滿足p i ≠ i, 就可以獲得Google Girl Hackathon的入場券。

妞妞僅允許的操作是: 交換排列中兩個相鄰的元素, 並且妞妞允許做這個操作任意次。

但是Google Girl Hackathon就快要開始了, 妞妞希望做最少的操作就使排列滿足要求, 妞妞希望你能幫助她。

 

輸入描述:
輸入包括兩行, 第一行包括一個正整數n(2 <= n <= 10^5), 表示排列的長度和范圍。
第二行包括n個正整數p

1

, p

2

, p

3

,...,p

n

, 即妞妞得到的排列, 保證是一個1~n的排列。

   輸出描述:

輸出一個整數, 表示妞妞需要的操作次數。

輸入例子1:
5
1 4 3 5 2

輸出例子1:
2
【分析】:如果某個數沒有滿足錯排要求,直接和相鄰的位置swap一下,統計次數即可。如果有一個pi=i或一對pi=i並且pi+1=i+1,則需要一次交換。
【代碼】:
作者:NotDeep
鏈接:https://www.nowcoder.com/discuss/65411
來源:牛客網

#include <bits/stdc++.h>
 
using namespace std;
 
const int maxn = 1e5 + 5;
 
int a[maxn], n;
int main() {
    cin >> n;
    for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    int res = 0;
    for(int i = 0; i < n - 1; i++) {
        if(a[i] == i + 1) {
            swap(a[i], a[i + 1]);
            res++;
        }
    }
    if(a[n - 1] == n) res++;
    cout << res << endl;
    return 0;
}
數論、錯排

 

作者:shiqitao
鏈接:https://www.nowcoder.com/discuss/65424?type=0&order=0&pos=6&page=0
來源:牛客網

#include <iostream>
using namespace std;
int main()
{
    int n; cin >> n;
    int equal = 0, count = 0, data;
    while (count < n) {
        cin >> data;
        if (data == ++count) {
            if (count != n) cin >> data;
            count++; equal++;
        }
    }
    cout << equal;
    return 0;
}
Code2

 

妞妞參加完Google Girl Hackathon之后,打車回到了牛家庄。

妞妞需要支付給出租車司機車費s元。妞妞身上一共有n個硬幣,第i個硬幣價值為p[i]元。

妞妞想選擇盡量多的硬幣,使其總價值足以支付s元車費(即大於等於s)。


但是如果從妞妞支付的這些硬幣中移除一個或者多個硬幣,剩下的硬幣總價值還是足以支付車費的話,出租車司機是不會接受的。例如: 妞妞使用價值為2,5,7的硬幣去支付s=11的車費,出租車司機是不會接受的,因為價值為2這個硬幣是可以移除的。


妞妞希望能選取最大數量的硬幣,使其總價值足以支付車費並且出租車司機能接受。

妞妞希望你能幫她計算最多可以支付多少個硬幣。

輸入描述:

輸入包括兩行, 第一行包括兩個正整數n和s(1 <= n <= 10, 1 <= s <= 1000), 表示妞妞的硬幣個數和需要支付的車費。
第二行包括n個正整數p[i] (1 <= p[i] <= 100),表示第i個硬幣的價值。
保證妞妞的n個硬幣價值總和是大於等於s。

輸出描述:

輸出一個整數, 表示妞妞最多可以支付的硬幣個數。

輸入例子1:

5 9
4 1 3 5 4

輸出例子1:

3
【分析】:最多只有10個硬幣,簡單遍歷一下就可以啦。注意到n很小,直接枚舉子集判斷是否合法,在所有合法的方案中找size最大。
【代碼】:
作者:shiqitao
鏈接:https://www.nowcoder.com/discuss/65424?type=0&order=0&pos=6&page=0
來源:牛客網

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int n, s; cin >> n >> s;
    int data[10] = { 0 };
    for (int i = 0; i < n; i++) {
        cin >> data[i];
    }
    int result = 0;
    for (int i = 0; i < pow(2, n); i++) {
        int mincoin = 10000, sum = 0, sumcoin = 0;
        int temp = i;
        for (int j = 0; j < n; j++) {
            if (temp % 2) {
                sum += data[j];
                mincoin = mincoin < data[j] ? mincoin : data[j];
                sumcoin++;
            }
            temp >>= 1;
        }
        result = sum >= s && sum - mincoin < s ? result>sumcoin ? result : sumcoin : result;
    }
    cout << result;
    return 0;
}
簡單遍歷一下

 

作者:NotDeep
鏈接:https://www.nowcoder.com/discuss/65411
來源:牛客網

#include <bits/stdc++.h>
 
using namespace std;
 
int n, s, p[15];
int main() {
    scanf("%d%d", &n, &s);
    for(int i = 0; i < n; i++) scanf("%d", &p[i]);
    int ans = 0;
    for (int x = 0; x < (1 << n); x++) {
        int mi = 10000000;
        int sum = 0;
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if ((x & (1 << i)) != 0 ) {
                mi = min(mi, p[i]);
                sum += p[i];
                cnt++;
            }
        }
        if (sum >= s && sum - mi < s) {
            ans = max(ans, cnt);
        }
    }
    cout << ans << endl;
 
}
O(2^n)

 

美麗的牛家庄受到了外星人的侵略, 勇敢的妞妞要上戰場抵御侵略。


在妞妞上戰場前, 村長牛牛給了妞妞N件裝備, 妞妞需要選擇其中的K件,裝備在身上提升自己的戰斗力。每件裝備有5種屬性增幅值,對於第i件裝備它的屬性增幅值為(ri1, ri2, ri3, ri4, ri5), 分別代表該裝備對不同的屬性值增幅。

當妞妞裝備多件裝備的時候,由於裝備之前會互相影響, 對於每種屬性值的增幅並不是所有裝備該屬性值之和, 而是該種屬性值下所有裝備中最大的屬性值。而妞妞最終增加的戰斗力為這5種屬性值增幅之和。


妞妞一定要保衛牛家庄, 所以她希望她能提升盡可能多的戰斗力, 請你幫幫她計算她最多能增加多少戰斗力。

輸入描述:

輸入包括N+1行,

第一行包括兩個正整數N和K(1 <= N <= 10000, 1 <= K <= N), 分別表示一共有的裝備數量和妞妞需要選擇的裝備數量。

接下來的N行,每行5個整數ri1, ri2, ri3, ri4, ri5 (0 <= ri1, ri2, ri3, ri4, ri5 <= 10000)表示第i件裝備的5種屬性值增幅。

輸出描述:
輸出一個整數,表示妞妞最多能增加的戰斗力。
輸入例子1:
4 2
30 30 30 30 0
50 0 0 0 0
0 50 0 50 10
0 0 50 0 20
輸出例子1:
170
例子說明1:
妞妞要從4件裝備中選取2件, 如果妞妞選擇第1件和第3件裝備,那么增加的戰斗力為30 + 50 + 30 + 50 + 10 = 170, 這是最大的方案。

【分析】:沒有想到好辦法,m大於等於5時取各個屬性的最大值,m小於等於3時遍歷,m等於4時為防止超時,用一點小小的技巧即可通過。
當k >= 5的時,每一維屬性都取最大求和即可。
對於k < 5的時,預處理31種情況可能得到的最大的和。然后dfs枚舉子集維護最大的答案即可。
【代碼】:
作者:shiqitao
鏈接:https://www.nowcoder.com/discuss/65424?type=0&order=0&pos=6&page=0
來源:牛客網

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int n, m; cin >> n >> m;
    int **r = new int*[n], result = 0;
    int maxr[5] = { 0 };
    for (int i = 0; i < n; i++) {
        r[i] = new int[5];
        for (int j = 0; j < 5; j++) {
            cin >> r[i][j];
            maxr[j] = max(maxr[j], r[i][j]);
        }
    }
    if (m == 1) {
        for (int i = 0; i < n; i++) {
            int temp = 0;
            for (int k = 0; k < 5; k++) {
                temp += r[i][k];
            }
            result = max(result, temp);
        }
    }
    else if (m == 2) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int temp = 0;
                for (int k = 0; k < 5; k++) {
                    temp += max(r[i][k], r[j][k]);
                }
                result = max(result, temp);
            }
        }
    }
    else if (m == 3) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int p = 0; p < n; p++) {
                    int temp = 0;
                    for (int k = 0; k < 5; k++) {
                        temp += max(max(r[i][k], r[j][k]), r[p][k]);
                    }
                    result = max(result, temp);
                }
            }
        }
    }
    else if (m == 4) {
        int maxtemp[5][5] = { 0 };
        for (int p = 0; p < 5; p++) {
            for (int q = p + 1; q < 5; q++) {
                int temp = 0;
                for (int i = 0; i < n; i++) {
                    temp = max(temp, r[i][p] + r[i][q]);
                }
                for (int k = 0; k < 5; k++) {
                    if (k != p && k != q) {
                        temp += maxr[k];
                    }
                }
                result = max(result, temp);
            }
        }
    }
    else {
        for (int k = 0; k < 5; k++) {
            result += maxr[k];
        }
    }
    cout << result;
    return 0;
}
冗長

 

作者:NotDeep
鏈接:https://www.nowcoder.com/discuss/65411
來源:牛客網

#include <bits/stdc++.h>
 
using namespace std;
 
const int maxn = 1e4 + 5;
 
int mx[10];
int num[maxn][10];
int N, K;
int sta[32];
int dfs(int s, int cur) {
    if(cur == K) return 0;
    int tmp = 0;
    for(int i = s; i; i = (i - 1) & s) tmp = max(tmp, sta[i] + dfs(s ^ i, cur + 1));
    return tmp;
}
int main() {
    scanf("%d%d", &N, &K);
    memset(sta, 0, sizeof(sta));
    memset(mx, 0, sizeof(mx));
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < 5; j++) {
            scanf("%d", &num[i][j]);
            mx[j] = max(mx[j], num[i][j]);
        }
        for(int j = 0; j < 32; j++) {
            int res = 0;
            for(int k = 0; k < 5; k++) {
                if(j & (1 << k)) {
                    res += num[i][k];
                }
            }
            sta[j] = max(sta[j], res);
        }
    }
    if(K >= 5) {
        int ans = 0;
        for(int i = 0; i < 5; i++) ans += mx[i];
        printf("%d\n", ans);
    } else {
        printf("%d\n", dfs(31, 0));
    }
    return 0;
}
DFS

如果一個整數x是某個整數的平方, 我們就把整數x稱為平方數。

妞妞最喜歡的數字就是平方數, 妞妞現在給你一個N, 妞妞希望你能幫助她找出不大於N的最大的平方數。

輸入描述:

輸入包括一行, 包括一個正整數N(1 <= N <= 10^9), 表示妞妞給的數字N。


輸出描述:

輸出一個整數, 即不大於N的最大的平方數。

輸入例子1:

10

輸出例子1:

9

【分析】:

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int n; cin >> n;
    cout << (int)sqrt(n)*(int)sqrt(n) << endl;
    return 0;
}


//////////////////////////////
#include <bits/stdc++.h>
using namespace std;
 
int n;
int main() {
    cin >> n;
    int ans = 0;
    for(int i = 0; i <= sqrt(n); i++) ans = i * i;
    printf("%d\n",ans);
    return 0;
 }
View Code

 

妞妞參加了Nowcoder Girl女生編程挑戰賽, 但是很遺憾, 她沒能得到她最喜歡的黑天鵝水晶項鏈。

於是妞妞決定自己來制作一條美麗的項鏈。一條美麗的項鏈需要滿足以下條件:

1、需要使用n種特定的水晶寶珠

2、第i種水晶寶珠的數量不能少於li顆, 也不能多於ri

3、一條美麗的項鏈由m顆寶珠組成

妞妞意識到滿足條件的項鏈種數可能會很多, 所以希望你來幫助她計算一共有多少種制作美麗的項鏈的方案。

輸入描述:

輸入包括n+1行, 第一行包括兩個正整數(1 <= n <= 20, 1 <= m <= 100), 表示水晶寶珠的種數和一條美麗的項鏈需要的水晶寶珠的數量。

接下來的n行, 每行兩個整數li, ri(0 <= li <= ri <= 10), 表示第i種寶珠的數量限制區間。


輸出描述:

輸出一個整數, 表示滿足限定條件的方案數。保證答案在64位整數范圍內。

輸入例子1:

3 5
0 3
0 3
0 3

輸出例子1:

12
【分析】:

首先為了方便,在輸入的時候,將 [li,ri] 的區間縮小為 [0,ri-li] 。
使用動態規划,DP[i][j]為用前i+1種珠寶制作數量為j的項鏈的方案數量。
DP[i][j+k]=DP[i-1][j],其中k屬於 [0,ri-li]。

可以通過母函數求解。
比較直接的就直接用背包dp算就行了。
【代碼】:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;
    int *R = new int[n], temp;
    for (int i = 0; i < n; i++) {
        cin >> temp >> R[i];
        R[i] -= temp;
        m -= temp;
    }
    long long int **DP = new long long int*[n];
    for (int i = 0; i < n; i++) {
        DP[i] = new long long int[m + 1];
        memset(DP[i], 0, sizeof(long long int)*(m + 1));
    }
    for (int i = 0; i <= R[0]; i++) {
        DP[0][i] = 1;
    }
    for (int i = 1; i < n; i++) {
        for (int j = 0; j <= R[i]; j++) {
            for (int k = 0; k <= m - j; k++) {
                DP[i][k + j] += DP[i - 1][k];
            }
        }
    }
    cout << DP[n - 1][m] << endl;
    delete[] R;
    for (int i = 0; i < n; i++) {
        delete[] DP[i];
    }
    delete[] DP;
    return 0;
}
DP

 

作者:NotDeep
鏈接:https://www.nowcoder.com/discuss/65411
來源:牛客網

#include <bits/stdc++.h>
using namespace std;
 
long long f[2][105];
 
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    memset(f, 0, sizeof(f));
    f[0][0] = 1;
    for (int i = 1; i <= n; i++) {
        memset(f[i & 1], 0, sizeof(f[i & 1]));
        int l, r;
        scanf("%d%d", &l, &r);
        for (int k = l; k <= r; k++)
            for (int j = m; j >= k; j--)
                f[i & 1][j] += f[i + 1 & 1][j - k];
    }
    printf("%lld\n", f[n & 1][m]);
    return 0;
}
母函數

 


免責聲明!

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



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