【爱奇艺】2018秋季校招编程题

共 道题:
1、拼凑三角形(Easy)
2、红和绿(Easy)
3、括号匹配深度(Easy)
4、奇异数
5、奶牛编号
6、空中旅行(Easy)
7、循环数比较
8、平方根问题
9、平方串(最长偶串)

  头文件占地方,就都不写了= =,代码都是测试过了的。

一、拼凑三角形

牛牛手中有三根木棍,长度分别是a,b,c。牛牛可以把任一一根木棍长度削短,牛牛的目标是让这三根木棍构成一个三角形,并且牛牛还希望这个三角形的周长越大越好。

输入描述: 输入包括一行,一行中有正整数a, b, c(1 ≤ a, b, c ≤ 100), 以空格分割
输出描述: 输出一个整数,表示能拼凑出的周长最大的三角形。

输入 1 2 3  输出 5

  两边之和大于第三边,整数,所以减一就可以了。

int main() {
	int a[3];
	for (int& ai : a) cin >> ai;
	sort(a, a + 3);
	const int res = (a[0] + a[1]) > a[2] ? (a[0] + a[1] + a[2]) : ((a[0] + a[1]) * 2 - 1);
	cout << res << endl;
}
二、红和绿

有排成一行的已经被染成红色或者绿色的正方形。可以选择任意一个正方形然后用红或绿进行染色,原始颜色将会被覆盖。
牛牛的目标是在完成染色之后,每个红色 R 都比每个绿色 G 距离最左侧近
牛牛想知道他最少需要涂染几个正方形。
如样例所示: s = RGRGR 我们涂染之后变成 RRRGG 满足要求了,涂染的个数为2,没有比这个更好的涂染方案。

输入描述: 输入包括一个字符串s,字符串s长度length(1 ≤ length ≤ 50),其中只包括 ‘R’ 或者 ‘G’,分别表示红色和绿色。
输出描述: 输出一个整数,表示牛牛最少需要涂染的正方形数量

输入 RGRGR  输出 2

  可以遍历所有可能的分界点,不过更简单的方法是,只需要遍历所有 R 的位置,要不就是这个 R 变成 G,要不就是它前边的所有 G 都变成 R

int main() {
	string s;
	cin >> s;
	int pre_gs = 0, min_steps = 0; // pre_gs: 当前位置前有多少 'G'
	for(const char& c : s) {
		if (c == 'G') ++pre_gs;
		else
			min_steps = min(min_steps + 1, pre_gs);
	}
	cout << min_steps << endl;
}
三、括号匹配深度

对于一个合法的括号序列我们又有以下定义它的深度:
1、空串""的深度是0
2、如果字符串"X"的深度是x,字符串"Y"的深度是y,那么字符串"XY"的深度为 max(x, y)
3、如果"X"的深度是 x,那么字符串 “(X)” 的深度是 x+1
例如:
"()()()“的深度是1,”((()))"的深度是3。
牛牛现在给你一个合法的括号序列,需要你计算出其深度。

输入描述: 输入包括一个合法的括号序列s,s长度length(2 ≤ length ≤ 50),序列中只包含’(‘和’)’。
输出描述: 输出一个正整数,即这个序列的深度。

输入 (())  输出 2

  左右括号的题一般用栈都很好做,遇到左括号就放到栈里,遇到有括号就pop出一个左括号(因为肯定合法,不需要什么判断)。这道题其实就是问栈里边最多的时候有多少个左括号。由于没有别的要进行处理的,甚至可以用一个 int 来当做栈,记录栈里边有多少左括号。

int main() {
	int lefts = 0, max_depth = 0;	// lefts: 栈里边有多少左括号
	char ch;
	while(cin >> ch) {
		if (ch == '(') ++lefts;
		else {
			max_depth = max(max_depth, lefts);
			--lefts;
		}
	}
	cout << max_depth << endl;
}
四、奇异数

如果一个数字满足以下条件,我们就称它为奇异数:
1、这个数字至少有两位
2、这个数的最低两位是相同的。
比如: 1488是一个奇异数,而3、112不是。

牛牛现在给出一个一个区间 [L, R],让你计算出在区间内有多少个奇异数
输入描述: 输入包括两个正整数L和R(1 ≤ L ≤ R ≤ 1012),以空格分割。
输出描述: 输出一个正整数,即区间内的奇异数的个数。

输入 10 20  输出 1

  这样的区间题,第一想法就应该是,能不能转成两个区间的相减,就好像 presum 这种感觉。这道题 [L, R] 的奇异数就可以转成,[1, R] 区间减去 [1, L - 1]区间。
  然后讨论奇异数定义,讨论闭区间的右端点
  1、对于一个两位数 n 来说,奇异数个数为 n / 11 个,比如[1, 23],就有 11、22 两个奇异数;
  2、对于 >= 100 的数来说,奇异数个数为 n / 100 * 10,再加上自身个位十位组成的两位数的情况,比如[1, 234] 就包括:
    (1)11、22 … 99、100;
    (2)111、122 … 199、200;
    (3)211、222、233。// 自身个位十位组成的两位数的情况
  共 23 个奇异数。

  两位数的情况,可以在三位数的情况中考虑到,两位数相当于百位及以上都是0的三位数。所以对于一个右端点 N 来说,[1, N] 区间内的奇异数个数就是:
  (N / 100 * 10) + (N % 100 / 11 + 1)
  (N / 100 * 10) 是三位数情况,即上边的 (1)、(2),(N % 100 / 11 + 1) 即个位十位组成的两位数(不包括 00),即上边的情况 (3),代码如下(所有都要用 long long):

int main() {
	long long l, r;
	cin >> l >> r;
	const long long ln = ((l - 1) / 100 * 10) + ((l - 1) % 100 / 11);	// [1, l-1]
	const long long rn = (r / 100 * 10) + (r % 100 / 11);				// [1, r]
	cout << rn - ln << endl;
}
五、奶牛编号

牛牛养了 n 只奶牛,牛牛想给每只奶牛编号。每个奶牛对于数字都有自己的喜好,第 i 只奶牛想要一个 1 和 x[i] 之间的整数(其中包含 1 和 x[i] )。
牛牛需要满足所有奶牛的喜好,请帮助牛牛计算牛牛有多少种给奶牛编号的方法,输出符合要求的编号方法总数。

输入描述: 输入包括两行,第一行一个整数 n(1 ≤ n ≤ 50),表示奶牛的数量 第二行为n个整数 x[i] (1 ≤ x[i] ≤ 1000)
输出描述: 输出一个整数,表示牛牛在满足所有奶牛的喜好上编号的方法数。因为答案可能很大,输出方法数对 1,000,000,007 的模。

输入 4 4 4 4 4  输出 24

  这样的大小 DFS 肯定是不行的,想了想其实就是数学题。先将奶牛按照 x[i] 从小到大排序,然后给第 0 头奶牛 x[0] 种编号方式,第 1 头奶牛 x[1] - 1 种编号方式,后边一次类推即可,所有方式数乘起来就是结果。

int main() {
	const int MOD = 1000000007;
	long long n, res = 1;
	cin >> n;
	vector<int> x(n);
	for (int& i : x) cin >> i;
	sort(x.begin(), x.end());
	for(int i = 0; i < n; ++i) {
		if(x[i] <= i) {
			cout << "0" << endl;
			return 0;
		}
		res = (res * (x[i] - i)) % MOD;
	}
	cout << res << endl;
}
六、空中旅行

牛牛有羊羊有属于自己的飞机。他们进行几次连续的飞行。f[i] 表示第 i 次飞行所需的燃油的升数。飞行只能按照 f 数组所描述的顺序进行。
起初飞机里有 s 升燃油,为了正常飞行,每次飞行前飞机内燃油量应大于等于此处飞行所需要的燃油量。请计算在不进行加油的情况下他们能进行的飞行次数。

输入描述: 输入包括两行,第一行包括两个整数n和s(1 ≤ n ≤ 50, 1 ≤ s ≤ 1000),分别表示计划飞行的次数和飞起初始状态下有的燃油量。 第二行包括n个整数f[i], (1 ≤ f[i] ≤ 1000), 表示每次计划飞行所需要的燃油量。
输出描述: 输出一个整数,表示他们能进行的飞行次数。

输入 7 10 1 2 3 4 5 6 7  输出 4

int main() {
	int n, s, cur, cnt = 0;
	cin >> n >> s;
	for(int i = 0; i < n; ++i) {
		cin >> cur;
		if (s < cur) break;
		++cnt;
		s -= cur;
	}
	cout << cnt << endl;
}
七、循环数比较

对于任意两个正整数x和k,我们定义repeat(x, k)为将 x 重复写 k 次形成的数,例如 repeat(1234, 3) = 123412341234,repeat(20, 2) = 2020。
牛牛现在给出4个整数x1, k1, x2, k2, 其中v1 = (x1, k1), v2 = (x2, k2),请你来比较 v1 和 v2 的大小。
输入描述: 输入包括一行,一行中有4个正整数x1, k1, x2, k2(1 ≤ x1,x2 ≤ 10^9, 1 ≤ k1,k2 ≤ 50),以空格分割
输出描述: 如果 v1 < v2 输出 “Less”,v1 == v2 输出 “Equal”,v1 > v2 输出 “Greater”.

输入 1010 3 101010 2  输出 Equal

  直接转成 string 比较即可。

int main() {
	string x1, x2, s1, s2;
	int k1, k2;
	cin >> x1 >> k1 >> x2 >> k2;
	if (x1.length() * k1 < x2.length() * k2) {
		printf("Less\n");
		return 0;
	}
	if (x1.length() * k1 > x2.length() * k2) {
		printf("Greater\n");
		return 0;
	}
	while(k1 != 0) {
		s1 += x1;
		--k1;
	}
	while (k2 != 0) {
		s2 += x2;
		--k2;
	}
	if (s1 < s2)		printf("Less\n");
	else if (s1 == s2)	printf("Equal\n");
	else				printf("Greater\n");
}
八、平方根问题

考虑定义在两正整数上的函数SSR(平方根之和的平方):SSR(A, B) = (sqrt(A) + sqrt(B))^2。
牛牛对函数值为整数的情况很感兴趣。现在给定整数n和m,请帮助牛牛计算有序对(A, B)的数量, 满足1 ≤ A ≤ n, 1 ≤ B ≤ m 而且 SSR(A, B)是一个整数。
输入描述: 输入包括两个整数 n和 m (1 ≤ n ≤ 105, 1 ≤ m ≤ 105)
输出描述: 输出一个整数,表示满足条件的有序对对数。

输入 3 8  输出 5

  平方打开之后,就是问 a b \sqrt{ab} ab 是整数的有序对数,但是暴力遍历会TLE,只能过 60%。先记录一下AC的,还没有看懂。

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

vector<bool> pend(100005, false);

void getPend(int m) {
	int rec;
	for (int i = 2, rec = i * i; rec <= m; i++, rec = i * i) {
		if (pend[rec])continue;
		for (int j = rec; j <= m; j += rec)
			pend[j] = true;
	}
}

int main() {
	int n, m;
	cin >> n >> m;
	int sn = (int)sqrt(n), sm = (int)sqrt(m); 
	long long ans = sn * sm;
	getPend(n > m ? m : n);
	for (int i = 2;; i++) {
		if (pend[i]) continue;
		if (n / i == 0 || m / i == 0) break;
		int nt = n / i, mt = m / i;
		int snt = (int)sqrt(nt), smt = (int)sqrt(mt);
		ans += snt * smt;
	}
	printf("%lld", ans);
}
九、平方串

如果一个字符串S是由两个字符串T连接而成,即S = T + T, 我们就称S叫做平方串,例如 “”,“aabaab”,“xxxx” 都是平方串.
牛牛现在有一个字符串s,请你帮助牛牛从s中移除尽量少的字符,让剩下的字符串是一个平方串。换句话说,就是找出s的最长子序列并且这个子序列构成一个平方串。
输入描述: 输入一个字符串s,字符串长度length(1 ≤ length ≤ 50),字符串只包括小写字符。
输出描述: 输出一个正整数,即满足要求的平方串的长度。

输入 frankfurt  输出 4

  没有想到什么特别好的方法,直接遍历每一个断点,然后对分开的两部分进行 LCS 计算(AC了),LCS(最长公共子序列)可以参考 https://blog.csdn.net/Bob__yuan/article/details/99690889

int LCS(string s1, string s2) {
	const int len1 = s1.length(), len2 = s2.length();
	vector<vector<int>> lcs(len1 + 1, vector<int>(len2 + 1, 0));
	for (int i = 0; i < len1; ++i)
		for (int j = 0; j < len2; ++j) {
			if (s1[i] == s2[j])
				lcs[i + 1][j + 1] = lcs[i][j] + 1;
			else
				lcs[i + 1][j + 1] = max(lcs[i][j + 1], lcs[i + 1][j]);
		}
	return lcs[len1][len2];
}

int main() {
	string s;
	cin >> s;
	int max_len = 0;
	for(size_t i = 1; i < s.length() - 1; ++i)
		max_len = max(max_len, 2 * LCS(s.substr(0, i), s.substr(i)));
	cout << max_len << endl;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值