牛客网--网易2018校招编程题合集
链接:https://www.nowcoder.com/questionTerminal/32c71b52db52424c89a565e4134bfe4e
来源:牛客网
小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币。
魔法机器1:如果投入x个魔法币,魔法机器会将其变为2x+1个魔法币
魔法机器2:如果投入x个魔法币,魔法机器会将其变为2x+2个魔法币
小易采购魔法神器总共需要n个魔法币,所以小易只能通过两台魔法机器产生恰好n个魔法币,小易需要你帮他设计一个投入方案使他最后恰好拥有n个魔法币。
输入描述:
输入包括一行,包括一个正整数n(1 ≤ n ≤ 10^9),表示小易需要的魔法币数量。
输出描述:
输出一个字符串,每个字符表示该次小易选取投入的魔法机器。其中只包含字符'1'和'2'。
输入
10
输出
122
逆推。
#include <cstdio> const int MAXN = 100000 + 10; int n, cnt, num[MAXN]; int main(){ while(scanf("%d", &n) != EOF){ cnt = 0; while(n){ if(n%2 == 1){ num[cnt++] = 1; n = (n - 1)/2; }else{ num[cnt++] = 2; n = (n - 2)/2; } } for(int i=cnt-1; i>=0; --i){ printf("%d", num[i] ); } printf(" "); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/ef6262d0381d42ebbe22d8a8554fef01?source=relative
来源:牛客网
为了得到一个数的"相反数",我们将这个数的数字顺序颠倒,然后再加上原先的数得到"相反数"。例如,为了得到1325的"相反数",首先我们将该数的数字顺序颠倒,我们得到5231,之后再加上原先的数,我们得到5231+1325=6556.如果颠倒之后的数字有前缀零,前缀零将会被忽略。例如n = 100, 颠倒之后是1.
输入描述:
输入包括一个整数n,(1 ≤ n ≤ 10^5)
输出描述:
输出一个整数,表示n的相反数
输入
1325
输出
6556
直接法。
#include <cstdio> int GetRev(int n){ int ans = 0; while(n){ ans = 10*ans + n%10; n /= 10; } return ans; } int main(){ int ans, n; while(scanf("%d", &n) != EOF){ ans = n + GetRev(n); printf("%d ", ans ); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/97bc02e432bb4744a9e666b6c93d4479?source=relative
来源:牛客网
输入描述:
输入包括一个字符串s,字符串s的长度length(1 ≤ length ≤ 50),s只含小写字母('a'-'z')
输出描述:
输出一个整数,表示所有碎片的平均长度,四舍五入保留两位小数。 如样例所示: s = "aaabbaaac" 所有碎片的平均长度 = (3 + 2 + 3 + 1) / 4 = 2.25
输入
aaabbaaac
输出
2.25
直接法。
#include <cstdio> #include <cstring> const int MAXN = 100 + 10; int main(){ int len, i = 0, cnt = 0, sum = 0; char ch[MAXN]; scanf("%s", ch); len = strlen(ch); while(i < len){ sum += 1; while(i + 1 < len && ch[i] == ch[i+1]){ ++sum; ++i; } ++cnt; ++i; } printf("%.2lf ", (1.0 * sum / cnt) ); return 0; }
链接:https://www.nowcoder.com/questionTerminal/f58859adc39f4edc9cd8e40ba4160339?source=relative
来源:牛客网
小易现在在0号城市,每次行动小易会从当前所在的城市走到与其相邻的一个城市,小易最多能行动L次。
如果小易到达过某个城市就视为小易游历过这个城市了,小易现在要制定好的旅游计划使他能游历最多的城市,请你帮他计算一下他最多能游历过多少个城市(注意0号城市已经游历了,游历过的城市不重复计算)。
输入描述:
输入包括两行,第一行包括两个正整数n(2 ≤ n ≤ 50)和L(1 ≤ L ≤ 100),表示城市个数和小易能行动的次数。 第二行包括n-1个整数parent[i](0 ≤ parent[i] ≤ i), 对于每个合法的i(0 ≤ i ≤ n - 2),在(i+1)号城市和parent[i]间有一条道路连接。
输出描述:
输出一个整数,表示小易最多能游历的城市数量。
输入
5 2 0 1 2 3
输出
3
树形dp,最经典的树形dp方法。
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; const int MAXN = 55; struct Node{ int v; Node *next; }; Node ed[2*MAXN], *head[MAXN]; int n, L, cnt, dp[2][MAXN][2*MAXN]; void AddEdge(int v, int u){ ed[cnt].v = v; ed[cnt].next = head[u]; head[u] = &ed[cnt++]; } void dfs(int fa, int cur){ Node *p; dp[1][cur][0] = 1; for(int i=1; i<=L; ++i){ dp[0][cur][i] = dp[1][cur][i] = 1; } for(p=head[cur]; p!=NULL; p=p->next){ int v = p->v; if(v == fa){ continue; } dfs(cur, v); for(int i=L; i>=0; --i){ int j = 0; for(; j+2<=i; ++j){ dp[1][cur][i] = max(dp[1][cur][i], dp[1][cur][j] + dp[1][v][i-j-2]); dp[0][cur][i] = max(dp[0][cur][i], dp[1][cur][j] + dp[0][v][i-j-1]); dp[0][cur][i] = max(dp[0][cur][i], dp[1][cur][j] + dp[1][v][i-j-1]); dp[0][cur][i] = max(dp[0][cur][i], dp[0][cur][j] + dp[1][v][i-j-2]); } if(j + 1 <= i){ dp[0][cur][i] = max(dp[0][cur][i], dp[1][cur][j] + dp[0][v][i-j-1]); dp[0][cur][i] = max(dp[0][cur][i], dp[1][cur][j] + dp[1][v][i-j-1]); } } } } int main(){ int ans, tmp; while(scanf("%d %d", &n, &L) != EOF){ memset(dp, 0, sizeof(dp)); memset(head, 0, sizeof(head)); cnt = 0; for(int i=1; i<n; ++i){ scanf("%d", &tmp); AddEdge(tmp, i); AddEdge(i, tmp); } dfs(0, 0); ans = max(dp[0][0][L], dp[1][0][L]); printf("%d ", ans ); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/a461395335c946c5b409e79847796cd0
来源:牛客网
牛博士给小易出了一个难题:
对数列A进行重新排列,使数列A满足所有的A[i] * A[i + 1](1 ≤ i ≤ N - 1)都是4的倍数。
小易现在需要判断一个数列是否可以重排之后满足牛博士的要求。
输入描述:
输入的第一行为数列的个数t(1 ≤ t ≤ 10), 接下来每两行描述一个数列A,第一行为数列长度n(1 ≤ n ≤ 10^5) 第二行为n个正整数A[i](1 ≤ A[i] ≤ 10^9)
输出描述:
对于每个数列输出一行表示是否可以满足牛博士要求,如果可以输出Yes,否则输出No。
输入
2 3 1 10 100 4 1 2 3 4
输出
Yes No
直接法,计算 可以被4整除的数的个数, 和不被2整除的个数,%4 个数 >= %2 mod 1 个数即可。
#include <cstdio> #include <cstring> const int MAXN = 100 + 10; int main(){ int n, t, c4, c1, TC; scanf("%d", &TC); while(TC--){ scanf("%d", &n); c1 = 0; c4 = 0; for(int i =0; i<n; ++i){ scanf("%d", &t); if(t % 4 == 0){ ++c4; }else if(t % 2 == 1){ ++c1; } } if( c4 >= c1 ){ printf("Yes "); }else{ printf("No "); } } return 0; }
链接:https://www.nowcoder.com/questionTerminal/504ad6420b314e5bb614e1684ad46d4d?source=relative
来源:牛客网
1. 空串""是合法的括号序列
2. 如果"X"和"Y"是合法的序列,那么"XY"也是一个合法的括号序列
3. 如果"X"是一个合法的序列,那么"(X)"也是一个合法的括号序列
4. 每个合法的括号序列都可以由上面的规则生成
例如"", "()", "()()()", "(()())", "(((()))"都是合法的。
从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。
例如"abcde"的子序列有"abe","","abcde"等。
定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。
小易给出一个合法的括号匹配序列s,小易希望你能找出具有以下特征的括号序列t:
1、t跟s不同,但是长度相同
2、t也是一个合法的括号匹配序列
3、LCS(s, t)是满足上述两个条件的t中最大的
因为这样的t可能存在多个,小易需要你计算出满足条件的t有多少个。
如样例所示: s = "(())()",跟字符串s长度相同的合法括号匹配序列有:
"()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )为4,其他三个都为5,所以输出3.
输入描述:
输入包括字符串s(4 ≤ |s| ≤ 50,|s|表示字符串长度),保证s是一个合法的括号匹配序列。
输出描述:
输出一个正整数,满足条件的t的个数。
输入
(())()
输出
3
转了一个弯,其实就是判断 len-1的LCS的s,这个s可以由插入一个字符串得到。(加上判断合法性即可)
#include <iostream> #include <unordered_map> #include <string> using namespace std; bool isLegal(string s){ int l = 0, r = 0; for(int i=0; i<s.length(); ++i){ if(s[i] == '('){ ++l; }else{ ++r; } if(r > l){ return false; } } return true; } int main(){ string s; cin >> s; int len = s.length(); unordered_map<string, int> mp; mp[ s ] = 1; int ans = 0; for(int i=0; i<len; ++i){ string t1 = s.substr(0, i) + s.substr(i+1); for(int j=0; j<len; ++j){ if(i == j){ continue; } string tmp = t1.substr(0, j) + s[i] + t1.substr(j); // cout << tmp << endl; if(isLegal(tmp) && mp.find(tmp) == mp.end()){ mp[ tmp ] = 1; ++ans; } } } cout << ans << endl; return 0; }