发布于 2017-03-22 08:33:44 | 300 次阅读 | 评论: 0 | 来源: PHPERZ
网易(163)
网易公司(NASDAQ:NTES),是中国领先的互联网技术公司,也是中国主要门户网站,和新浪网、搜狐网、腾讯网并称为“中国四大门户网站”。网易在开发互联网应用、服务及其它技术方面始终保持中国业内界的领先地位。
如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列。例如:
{1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列,
{1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列。
现在给出一个数字序列,允许使用一种转换操作:
选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个数之前的位置(只插入一个和)。
现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列。
思路:递归,如果最左小于最右,合并左边,如果最右小于最左,合并右边,直到是回文(极限情况直接合成一个数),有点类似快排中的一小部分思路
#include <iostream>
using namespace std;
int getTimes(int* nums, int head, int tail) {
int times = 0;
int left = nums[head], right = nums[tail];
while (head < tail && left != right) {
if (left < tail) {
++head;
left += nums[head];
++times;
}
else {
--tail;
right += nums[tail];
++times;
}
}
if (head >= tail)
return times;
else
times += getTimes(nums, ++head, --tail);
}
int main() {
int n;
while (cin >> n) {
int nums[40];
for (int i = 0; i < n; ++i) {
cin >> nums[i];
}
cout << getTimes(nums, 0, n - 1) << endl;
}
}
小易有一个圆心在坐标原点的圆,小易知道圆的半径的平方。小易认为在圆上的点而且横纵坐标都是整数的点是优雅的,小易现在想寻找一个算法计算出优雅的点的个数,请你来帮帮他。
例如:半径的平方如果为25
优雅的点就有:(+/-3, +/-4), (+/-4, +/-3), (0, +/-5) (+/-5, 0),一共12个点。
思路:满足的点的横坐标绝对值 <= 半径 , 将给出的数开方,然后递减遍历,即可得到结果
#include<iostream>
using namespace std;
int main() {
int n;
while (cin >> n) {
int res = 0;
int x = (int)sqrt(n);
while (x) {
double y = sqrt(n - x * x);
if (y - (int)y == 0) {
res += 4;
}
--x;
}
cout << res << endl;
}
}
小易来到了一条石板路前,每块石板上从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号石板
思路:
首先求得约数,存数组,计入动态规划的步数
可移动的步数随着前进,一直在更新
建立动态规划数组,初始化为0,将起点初始化为1
从起点开始计算可到达的点,若此点未到达过,则更新为到达此点需要的步数
若此点之前到达过,则比较到达步数,留较小的到达步数。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void getStep(int n, vector<int> &step) {
for (int i = 2; i <= sqrt(n); ++i) {
if(n % i == 0) {
step.push_back(i);
if (n / i != i) {
step.push_back(n / i);
}
}
}
}
int main() {
int n, m;
while (cin >> n >> m) {
vector<int> dp(m + 1, 0);
dp[n] = 1;
for (int i = n; i <= m; ++i) {
vector<int> step;
getStep(i, step);
if (dp[i] == 0)
continue;
for (int j = 0; j < step.size(); ++j) {
if (step[j] + i <= m) {
if (dp[step[j] + i] == 0)
dp[step[j] + i] = dp[i] + 1;
else
dp[step[j] + i] = min(dp[i] + 1, dp[step[j] + i]);
}
}
}
if (dp[m])
cout << dp[m] - 1 << endl;
else
cout << -1 << endl;
}
}
一个只包含’A’、’B’和’C’的字符串,如果存在某一段长度为3的连续子串中恰好’A’、’B’和’C’各有一个,那么这个字符串就是纯净的,否则这个字符串就是暗黑的。例如:
BAACAACCBAAA 连续子串”CBA”中包含了’A’,’B’,’C’各一个,所以是纯净的字符串
AABBCCAABB 不存在一个长度为3的连续子串包含’A’,’B’,’C’,所以是暗黑的字符串
你的任务就是计算出长度为n的字符串(只包含’A’、’B’和’C’),有多少个是暗黑的字符串。
思路: DP
对于长度为n的字符串
f(n)表示总共的黑暗字符串的个数
s(n)表示在当前字符串中结尾两个字符相同的字符串的个数
d(n)表示在当前字符串中结尾两个字符不同的字符串的个数
即有
f(n) = s(n) + d(n)
f(n - 1) = s(n - 1) + d(n - 1)
长度为n的字符串比长度为n-1的字符串多出的个数应为
如果对于n-1中结尾两位字符相同的情况,则有3种情况可选
如果对于n-1中结尾两位字符不同的情况,则有2种情况可选
因此
f(n) = 3 * s(n - 1) + 2 * d(n - 1) = 2 * f(n - 1) + s(n - 1)
再寻找 s(n) d(n) 与 s(n - 1) d(n - 1)的关系
首先
s(n) + d(n) = 3 * s(n - 1) + 2 * d(n - 1)
对于字符串中末位两位相同的情况
如 ***AA
在增加一位字符之后的情况是 AAA, AAB, AAC
此时后两位字符相同的情况占1/3
对于字符串中末位两位不同的情况
如 ***AB
在增加一位字符之后的情况是 ABA, ABB
此时后两位字符相同的情况占1/2
再由 s(n) + d(n) = 3 * s(n - 1) + 2 * d(n - 1)
可以得到
s(n) = s(n - 1) + d(n - 1) = f(n - 1)
d(n) = 2 * s(n - 1) + d(n - 1)
因此得到最终结果
f(n) = 3 * s(n - 1) + 2 * d(n - 1)
= 2 * f(n - 1) + s(n - 1)
= 2 * f(n - 1) + f(n - 2)
#include<iostream>
#include<math.h>
using namespace std;
int main() {
int n;
while (cin >> n) {
long long int dp[50] = { 0 };
dp[1] = 3;
dp[2] = 9;
for (int i = 3; i <= n; ++i) {
dp[i] = 2 * dp[i - 1] + dp[i - 2];
}
cout << dp[n] << endl;
}
}
对于一个整数X,定义操作rev(X)为将X按数位翻转过来,并且去除掉前导0。例如:
如果 X = 123,则rev(X) = 321;
如果 X = 100,则rev(X) = 1.
现在给出整数x和y,要求rev(rev(x) + rev(y))为多少?
逆序,考虑前导0的情况
#include <iostream>
#include <string>
using namespace std;
int rev(int x);
int main() {
int x, y;
cin >> x >> y;
cout << rev(rev(x) + rev(y)) << endl;
system("pause");
return 0;
}
int rev(int x) {
string s = to_string(x);
int len = s.size();
for (int i = 0; i < len / 2; ++i) {
swap(s[i], s[len - i - 1]);
}
x = stoi(s);
while (x % 10 == 0){
x /= 10;
}
return x;
}
小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数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
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。
思路:找规律:如果这个数本书是奇数,直接返回, 否则将这个数除以2,知道数为奇数为止
代码
#include <iostream>
using namespace std;
int f(int x) {
while (x) {
if (x % 2 == 1)
break;
else
x >>= 1;
}
return x;
}
int main() {
int n;
while (cin >> n) {
int res = 0;
for (int i = 1; i <= n; ++i)
res += f(i);
cout << res << endl;
}
}
小易去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个每袋的包装(包装不可拆分)。 可是小易现在只想购买恰好n个苹果,小易想购买尽量少的袋数方便携带。如果不能购买恰好n个苹果,小易将不会购买。
思路: 贪心遍历即可
后续实际做的时候,可以发现有规律, 大于10的偶数均可以找到解,并且数列存在规律
#include <iostream>
using namespace std;
int findN(int n) {
int round = n / 6;
for (int i = 0; i <= round; ++i) {
if ((n - i * 6) % 8 == 0)
return i + (n - i * 6) / 8;
}
return -1;
}
int main() {
int n;
while (cin >> n) {
cout << findN(n) << endl;
}
}
A,B,C三个人是好朋友,每个人手里都有一些糖果,我们不知道他们每个人手上具体有多少个糖果,但是我们知道以下的信息:
A - B, B - C, A + B, B + C. 这四个数值.每个字母代表每个人所拥有的糖果数.
现在需要通过这四个数值计算出每个人手里有多少个糖果,即A,B,C。这里保证最多只有一组整数A,B,C满足所有题设条件。
计算结果满足条件即可,详见代码
#include<iostream>
using namespace std;
int main() {
int subAB, subBC, addAB, addBC;
int A, B, C;
cin >> subAB >> subBC >> addAB >> addBC;
A = (subAB + addAB) / 2;
B = (addAB - subAB) / 2;
C = (addBC - subBC) / 2;
if (A + B == addAB && A - B == subAB && B + C == addBC && B - C == subBC)
cout << A << ' ' << B << ' ' << C << endl;
else
cout << "No" << endl;
system("pause");
return 0;
}