网易2017秋招编程题集合-牛客网
链接:https://www.nowcoder.com/questionTerminal/0147cbd790724bc9ae0b779aaf7c5b50
来源:牛客网
如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列。例如:
{1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列,
{1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列。
现在给出一个数字序列,允许使用一种转换操作:
选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个数之前的位置(只插入一个和)。
现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列。
输入描述:
输入为两行,第一行为序列长度n ( 1 ≤ n ≤ 50) 第二行为序列中的n个整数item[i] (1 ≤ iteam[i] ≤ 1000),以空格分隔。
输出描述:
输出一个数,表示最少需要的转换次数
输入例子:
4 1 1 1 3
输出例子:
2
根据回文的现象,使用夹逼法。 注意最后需要判断两端是否一致,不一致的话则合并。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int MAXN = 55; int n, num[MAXN]; int main(){ freopen("in.txt", "r", stdin); int l, r, l_val, r_val, cnt; while(scanf("%d", &n) != EOF){ for(int i=0; i<n; ++i){ scanf("%d", &num[i]); } cnt = 0; l = 0; r = n-1; l_val = 0; r_val = 0; while(l <= r){ if(l_val == r_val){ l_val = num[l]; l++; r_val = num[r]; r--; }else if(l_val > r_val){ r_val += num[r]; r--; cnt++; }else{ l_val += num[l]; l++; cnt++; } } if(l_val != r_val){ cnt++; } printf("%d\n", cnt); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/0960cb46233b446687b77facc9148b89
来源:牛客网
小易有一个圆心在坐标原点的圆,小易知道圆的半径的平方。小易认为在圆上的点而且横纵坐标都是整数的点是优雅的,小易现在想寻找一个算法计算出优雅的点的个数,请你来帮帮他。
例如:半径的平方如果为25
优雅的点就有:(+/-3, +/-4), (+/-4, +/-3), (0, +/-5) (+/-5, 0),一共12个点。
输入描述:
输入为一个整数,即为圆半径的平方,范围在32位int范围内。
输出描述:
输出为一个整数,即为优雅的点的个数
输入例子:
25
输出例子:
12
判断约数。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; int main(){ int n, cnt, l, r; while(scanf("%d", &n) != EOF){ if(n == 0){ printf("%d\n", 1); continue; } l = 0; r = int(sqrt(n)) + 1; cnt = 0; while(l <= r){ if(l*l + r*r == n){ if(l == 0){ cnt += 2; }else if(l == r){ cnt += 2; }else{ cnt += 4; } l++; r--; }else if(l*l + r*r > n){ r--; }else{ l++; } } printf("%d\n", 2*cnt ); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/4284c8f466814870bae7799a07d49ec8
来源:牛客网
小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3.......
这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的
石板,小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
例如:
N = 4,M = 24:
4->6->8->12->18->24
于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板
输入描述:
输入为一行,有两个整数N,M,以空格隔开。 (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)
输出描述:
输出小易最少需要跳跃的步数,如果不能到达输出-1
输入例子:
4 24
输出例子:
5 使用bfs,并且设置一个vis来判断不走走过的路。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int MAXN = 1000000; int sq[2*MAXN], sq_step[2*MAXN], vis[MAXN]; int main(){ int n, m, tail, head, ans, tmp_step, tmp, t; while(scanf("%d %d", &n, &m) != EOF){ memset(vis, 0, sizeof(vis)); head = 0; tail = 0; sq[head] = n; sq_step[head++] = 0; vis[n] = 1; ans = -1; while(head > tail){ tmp = sq[tail]; tmp_step = sq_step[tail++]; if(tmp == m){ ans = tmp_step; break; } for(int i=2; i*i<=tmp; ++i){ if(tmp%i == 0){ t = tmp + i; if(t <= m && vis[t] == 0){ vis[t] = 1; sq[head] = t; sq_step[head++] = tmp_step + 1; } t = tmp + tmp/i; if(t <= m && vis[t] == 0){ vis[t] = 1; sq[head] = t; sq_step[head++] = tmp_step + 1; } } } } printf("%d\n", ans ); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/7e7ccd30004347e89490fefeb2190ad2
来源:牛客网
一个只包含‘A‘、‘B‘和‘C‘的字符串,如果存在某一段长度为3的连续子串中恰好‘A‘、‘B‘和‘C‘各有一个,那么这个字符串就是纯净的,否则这个字符串就是暗黑的。例如:
BAACAACCBAAA 连续子串"CBA"中包含了‘A‘,‘B‘,‘C‘各一个,所以是纯净的字符串
AABBCCAABB 不存在一个长度为3的连续子串包含‘A‘,‘B‘,‘C‘,所以是暗黑的字符串
你的任务就是计算出长度为n的字符串(只包含‘A‘、‘B‘和‘C‘),有多少个是暗黑的字符串。
输入描述:
输入一个整数n,表示字符串长度(1 ≤ n ≤ 30)
输出描述:
输出一个整数表示有多少个暗黑字符串
输入例子:
2 3
输出例子:
9 21
不知道我的dp公式为啥不对,init() 是我自己的公式,没找到哪里不对。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 35; long long dp[3][MAXN]; void init(){ dp[0][1] = dp[1][1] = dp[2][1] = 1; dp[0][2] = dp[1][2] = dp[2][2] = 3; for(int i=3; i<MAXN; ++i){ dp[0][i] = dp[0][i-1] + (dp[1][i-1] - dp[2][i-2]) + (dp[2][i-1] - dp[1][i-2]); dp[1][i] = dp[1][i-1] + (dp[2][i-1] - dp[0][i-2]) + (dp[0][i-1] - dp[2][i-2]); dp[2][i] = dp[2][i-1] + (dp[1][i-1] - dp[0][i-2]) + (dp[0][i-1] - dp[1][i-2]); } } void init2(){ dp[0][2] = 3; dp[1][2] = 6; for(int i=3; i<MAXN; ++i){ dp[0][i] = dp[0][i-1] + dp[1][i-1]; dp[1][i] = 2*dp[0][i-1] + dp[1][i-1]; } } int main(){ int n; long long ans; init2(); while(scanf("%d", &n) != EOF){ ans = dp[0][n] + dp[1][n]; // + dp[2][n]; printf("%lld\n", ans); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/bc62febdd1034a73a62224affe8bddf2
来源:牛客网
对于一个整数X,定义操作rev(X)为将X按数位翻转过来,并且去除掉前导0。例如:
如果 X = 123,则rev(X) = 321;
如果 X = 100,则rev(X) = 1.
现在给出整数x和y,要求rev(rev(x) + rev(y))为多少?
输入描述:
输入为一行,x、y(1 ≤ x、y ≤ 1000),以空格隔开。
输出描述:
输出rev(rev(x) + rev(y))的值
输入例子:
123 100
输出例子:
223
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; int REV(int val){ int ans = 0; while(val){ ans = 10*ans + val%10; val = val/10; } return ans; } int main(){ int n, m, ans; while(scanf("%d %d", &n, &m) != EOF){ ans = REV( REV(n) + REV(m) ); printf("%d\n", ans ); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/49cb3d0b28954deca7565b8db92c5296
来源:牛客网
小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。
例如:f(44) = 11.
现在给出一个N,需要求出 f(1) + f(2) + f(3).......f(N)
例如: N = 7
f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 3
+ 7 = 21
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。
输入描述:
输入一个整数N (1 ≤ N ≤ 1000000000)
输出描述:
输出一个整数,即为f(1) + f(2) + f(3).......f(N)
输入例子:
7
输出例子:
21
使用dfs,使用求和公式 对 1-n的所有奇数进行求和,然后再对偶数折半,求其dfs。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; long long dfs(int n){ if(n <= 0){ return 0; } if(n == 1 ){ return 1; } if(n%2 == 0){ return dfs(n/2) + (long long)(n-1+1)*(n/2)/2; }else{ return dfs((n-1)/2) + (long long)(n+1)*((n+1)/2)/2; } } int main(){ int n; long long ans; while(scanf("%d", &n) != EOF){ ans = dfs(n); printf("%lld\n", ans ); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/61cfbb2e62104bc8aa3da5d44d38a6ef
来源:牛客网
小易去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个每袋的包装(包装不可拆分)。 可是小易现在只想购买恰好n个苹果,小易想购买尽量少的袋数方便携带。如果不能购买恰好n个苹果,小易将不会购买。
输入描述:
输入一个整数n,表示小易想购买n(1 ≤ n ≤ 100)个苹果
输出描述:
输出一个整数表示最少需要购买的袋数,如果不能买恰好n个苹果则输出-1
输入例子:
20
输出例子:
3
多重背包问题。简易版。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int MAXN = 105; int num[MAXN]; void init(){ memset(num, 0x3f3f3f3f, sizeof(num)); num[0] = 0; for(int i=6; i<MAXN; ++i){ num[i] = min(num[i], num[i-6] + 1); } for(int i=8; i<MAXN; ++i){ num[i] = min(num[i], num[i-8] + 1); } } int main(){ init(); int n, ans; while(scanf("%d", &n) != EOF){ if(num[n] != 0x3f3f3f3f){ ans = num[n]; }else{ ans = -1; } printf("%d\n", ans ); } return 0; }
链接:https://www.nowcoder.com/questionTerminal/02d8d42b197646a5bbd0a98785bb3a34
来源:牛客网
A,B,C三个人是好朋友,每个人手里都有一些糖果,我们不知道他们每个人手上具体有多少个糖果,但是我们知道以下的信息:
A - B, B - C, A + B, B + C. 这四个数值.每个字母代表每个人所拥有的糖果数.
现在需要通过这四个数值计算出每个人手里有多少个糖果,即A,B,C。这里保证最多只有一组整数A,B,C满足所有题设条件。
输入描述:
输入为一行,一共4个整数,分别为A - B,B - C,A + B,B + C,用空格隔开。 范围均在-30到30之间(闭区间)。
输出描述:
输出为一行,如果存在满足的整数A,B,C则按顺序输出A,B,C,用空格隔开,行末无空格。 如果不存在这样的整数A,B,C,则输出No
输入例子:
1 -2 3 4
输出例子:
2 1 3
#include <cstdio> int main(){ int a, b, c, d, flag; int ans_a, ans_b, ans_c; while(scanf("%d%d%d%d", &a, &b, &c, &d) != EOF){ flag = 0; if((a+c)%2 == 0){ ans_a = (a+c)/2; }else{ flag = 1; } if((b+d)%2 == 0){ ans_b = (b+d)/2; }else{ flag = 1; } if(flag==0){ ans_c = ans_b - b; } if(flag==0 && (ans_a - ans_b)==a && (ans_b - ans_c)==b && (ans_a+ans_b)==c && (ans_b+ans_c)==d){ printf("%d %d %d\n", ans_a, ans_b, ans_c ); }else{ printf("No\n"); } } return 0; }