字节跳动OJ

 链接:https://www.nowcoder.com/questionTerminal/c0803540c94848baac03096745b55b9b
来源:牛客网
 

[编程题]万万没想到之抓捕孔连顺 -- 动态规划

我叫王大锤,是一名特工。我刚刚接到任务:在字节跳动大街进行埋伏,抓捕恐怖分子孔连顺。和我一起行动的还有另外两名特工,我提议

 

1. 我们在字节跳动大街的N个建筑中选定3个埋伏地点。

2. 为了相互照应,我们决定相距最远的两名特工间的距离不超过D。

 

我特喵是个天才! 经过精密的计算,我们从X种可行的埋伏方案中选择了一种。这个方案万无一失,颤抖吧,孔连顺!

……

万万没想到,计划还是失败了,孔连顺化妆成小龙女,混在cosplay的队伍中逃出了字节跳动大街。只怪他的伪装太成功了,就是杨过本人来了也发现不了的!

 

请听题:给定N(可选作为埋伏点的建筑物数)、D(相距最远的两名特工间的距离的最大值)以及可选建筑的坐标,计算在这次行动中,大锤的小队有多少种埋伏选择。

注意:

1. 两个特工不能埋伏在同一地点

2. 三个特工是等价的:即同样的位置组合(A, B, C) 只算一种埋伏方法,不能因“特工之间互换位置”而重复使用

 

输入描述:

第一行包含空格分隔的两个数字 N和D(1 ≤ N ≤ 1000000; 1 ≤ D ≤ 1000000)

第二行包含N个建筑物的的位置,每个位置用一个整数(取值区间为[0, 1000000])表示,从小到大排列(将字节跳动大街看做一条数轴)

输出描述:

一个数字,表示不同埋伏方案的数量。结果可能溢出,请对 99997867 取模

示例1

输入

4 3
1 2 3 4

输出

4

说明

可选方案 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)

示例2

输入

5 19
1 10 20 30 50

输出

1

说明

可选方案 (1, 10, 20)

 

动态规划

i位置固定,在以i为圆心的,半径为D的左半圆范围-->确定左边界j

#include<iostream>
#include<vector>

using namespace std;


long long C_n_k(int n, int k) {
	if (n < k)return 0;
	vector<long long> cur(n + 1, 0);
	vector<vector<long long> > c(n + 1, cur);
	c[1][0] = c[1][1] = 1;
	for (int i = 2; i <= n; i++) {
		for (int j = 0; j <= i; j++) {

			if (j == 0 || j == i)
				c[i][j] = 1;
			else
				c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
		}
	}

	return c[n][k];


}

long long C(long long n) {
	
	return n * (n - 1) / 2;

}

int main() {
	long long  N, D;
	cin >> N >> D;
	long long cnt = 0;
	vector<long long> pos(N, 0);
	cin >> pos[0] >> pos[1];
	for (int i = 2, j=0; i < N; i++) {
		cin >> pos[i];
	
			while (pos[i] - pos[j] >D) {
				j++;
			}
			cnt += C(i - j);
		

	}
	cout << cnt%99997867 ;
	system("pause");
}

 

[编程题] 雀魂启动!--递归

时间限制:1秒

空间限制:32768K

小包最近迷上了一款叫做雀魂的麻将游戏,但是这个游戏规则太复杂,小包玩了几个月了还是输多赢少。

于是生气的小包根据游戏简化了一下规则发明了一种新的麻将,只留下一种花色,并且去除了一些特殊和牌方式(例如七对子等),具体的规则如下:

 

  1. 总共有36张牌,每张牌是1~9。每个数字4张牌。
  2. 你手里有其中的14张牌,如果这14张牌满足如下条件,即算作和牌
  • 14张牌中有2张相同数字的牌,称为雀头。
  • 除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)

 

例如:

1 1 1 2 2 2 6 6 6 7 7 7 9 9 可以组成1,2,6,7的4个刻子和9的雀头,可以和牌

1 1 1 1 2 2 3 3 5 6 7 7 8 9 用1做雀头,组123,123,567,789的四个顺子,可以和牌

1 1 1 2 2 2 3 3 3 5 6 7 7 9 无论用1 2 3 7哪个做雀头,都无法组成和牌的条件。

 

现在,小包从36张牌中抽取了13张牌,他想知道在剩下的23张牌中,再取一张牌,取到哪几种数字牌可以和牌。

 

输入描述:

输入只有一行,包含13个数字,用空格分隔,每个数字在1~9之间,数据保证同种数字最多出现4次。

 

输出描述:

输出同样是一行,包含1个或以上的数字。代表他再取到哪些牌可以和牌。若满足条件的有多种牌,请按从小到大的顺序输出。若没有满足条件的牌,请输出一个数字0

 

输入例子1:

1 1 1 2 2 2 5 5 5 6 6 6 9

 

输出例子1:

9

 

例子说明1:

可以组成1,2,6,7的4个刻子和9的雀头

 

输入例子2:

1 1 1 1 2 2 3 3 5 6 7 8 9

 

输出例子2:

4 7

 

例子说明2:

用1做雀头,组123,123,567或456,789的四个顺子

 

输入例子3:

1 1 1 2 2 2 3 3 3 5 7 7 9

 

输出例子3:

0

 

例子说明3:

来任何牌都无法和牌
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

void dfs(vector<int> map, int que, int ke, vector<int> stack) {

	for (int i = 1; i <= 9; i++) {
		if (map[i] == 2) {
			map[i]--;
			stack.push_back(i);
		}
		else if (map[i] == 3) {

		}
		else if (map[i] == 1) {
			stack.push_back(i);
			map[i]--;
			dfs(map, que, ke, stack);
			map[i]++;
			stack.pop_back();
		}
		
	}
}

bool is_hu(vector<int> v,bool que) {
	if (v.empty())return true;
	int count0 = 1;
	for (int i = 1; i < v.size(); i++) {
		if (v[i] == v[0])
			count0++;
		else
			break;
	}
	if (count0 >= 2) {
		vector<int> newv2(v.begin() + 2, v.end());
		if (!que && is_hu(newv2, true))
			return true;
		
	}
	if (count0 >= 3) {
		vector<int> newv3(v.begin() + 3, v.end());
		if(is_hu(newv3, que))return true;
	}
	if (count(v.begin(), v.end(), v[0] + 1) > 0 && count(v.begin(), v.end(), v[0] + 2) > 0) {
		vector<int> newv1(v.begin() + 1, v.end());
		newv1.erase(find(newv1.begin(), newv1.end(), v[0] + 1));
		newv1.erase(find(newv1.begin(), newv1.end(), v[0] + 2));
		if (is_hu(newv1,que))
			return true;

	}
	return false;
	
}
bool hu(vector<int> v,bool que) {
	sort(v.begin(), v.end());
	return is_hu(v, que);
}
int main() {

	int N = 13;
	vector<int> v(13, 0);
	vector<int> map(10, 0);
	vector<int> res;
	bool que = false;
	int ke = 0,four = 0;
	for (int i = 0; i < N; i++) {
		cin >> v[i];
		map[v[i]]++;
	}
	for (int i = 1; i <=9; i++)
	{
		que = false;
		vector<int> cur_v(v);
		if (map[i] != 4) {
			map[i]++;
			cur_v.push_back(i);

			if (hu(cur_v,que)) {
				res.push_back(i);
				
			}
			map[i]--;
		}
	}
	if (res.size() == 0)
		cout << 0 << endl;
	for (int i = 0; i < res.size(); i++)
	{
		if (i == 0)
			cout << res[i];
		else
			cout <<" "<<res[i];
	}
	system("pause");
}

[编程题] 特征提取 -- 去重

时间限制:1秒

空间限制:32768K

       小明是一名算法工程师,同时也是一名铲屎官。某天,他突发奇想,想从猫咪的视频里挖掘一些猫咪的运动信息。为了提取运动信息,他需要从视频的每一帧提取“猫咪特征”。一个猫咪特征是一个两维的vector<x, y>。如果x_1=x_2 and y_1=y_2,那么这俩是同一个特征。

       因此,如果喵咪特征连续一致,可以认为喵咪在运动。也就是说,如果特征<a, b>在持续帧里出现,那么它将构成特征运动。比如,特征<a, b>在第2/3/4/7/8帧出现,那么该特征将形成两个特征运动2-3-4 和7-8。

现在,给定每一帧的特征,特征的数量可能不一样。小明期望能找到最长的特征运动。

 

输入描述:

第一行包含一个正整数N,代表测试用例的个数。

每个测试用例的第一行包含一个正整数M,代表视频的帧数。

接下来的M行,每行代表一帧。其中,第一个数字是该帧的特征个数,接下来的数字是在特征的取值;比如样例输入第三行里,2代表该帧有两个猫咪特征,<1,1>和<2,2>
所有用例的输入特征总数和<100000

N满足1≤N≤100000,M满足1≤M≤10000,一帧的特征个数满足 ≤ 10000。
特征取值均为非负整数。

 

输出描述:

对每一个测试用例,输出特征运动的长度作为一行

 

输入例子1:

1
8
2 1 1 2 2
2 1 1 1 4
2 1 1 2 2
2 2 2 1 4
0
0
1 1 1
1 1 1

 

输出例子1:

3

 

例子说明1:

特征<1,1>在连续的帧中连续出现3次,相比其他特征连续出现的次数大,所以输出3

 

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
using namespace std;

int main() {
	int N, M;   
	cin >> N ;
	for (int i = 0; i < N; i++) {
		cin >> M;
		vector<string> cur;
		map<string, int> m;
		vector<vector<string> > frame(M, cur);
		int max = -1;
		for (int i = 0; i < M; i++)
		{
			int num, x, y;
			string xy;
			cin >> num;
			for (int j = 0; j < num; j++) {
				cin >> x >> y;
				xy = to_string(x) + to_string(y);
				frame[i].push_back(xy);
				if (i == 0) {
					m[xy]++;
					if (m[xy] > max) {
						max = m[xy];
					}
				}
					
				else {
					if (find(frame[i - 1].begin(), frame[i - 1].end(), xy) != frame[i - 1].end()) {
						m[xy]++;
						if (m[xy] > max) {
							max = m[xy];
						}
					}
					else {
						m[xy] = 1;
					}
				}
			}
		}
		cout << max << endl;

	}
	
	
	system("pause");
}

链接:https://www.nowcoder.com/questionTerminal/7aa6e186a50b4ac5875eda5f924b9bdb?toCommentId=3184237
来源:牛客网
 

用户喜好--map查询

为了不断优化推荐效果,今日头条每天要存储和处理海量数据。假设有这样一种场景:我们对用户按照它们的注册时间先后来标号,对于一类文章,每个用户都有不同的喜好值,我们会想知道某一段时间内注册的用户(标号相连的一批用户)中,有多少用户对这类文章喜好值为k。因为一些特殊的原因,不会出现一个查询的用户区间完全覆盖另一个查询的用户区间(不存在L1<=L2<=R2<=R1)。

 

 

输入描述:

输入: 第1行为n代表用户的个数 第2行为n个整数,第i个代表用户标号为i的用户对某类文章的喜好度 第3行为一个正整数q代表查询的组数  第4行到第(3+q)行,每行包含3个整数l,r,k代表一组查询,即标号为l<=i<=r的用户中对这类文章喜好值为k的用户的个数。 数据范围n <= 300000,q<=300000 k是整型


 

输出描述:

输出:一共q行,每行一个整数代表喜好值为k的用户的个数

示例1

输入

5
1 2 3 3 5
3
1 2 1
2 4 5
3 5 3

输出

1
0
2

说明

样例解释:
有5个用户,喜好值为分别为1、2、3、3、5,
第一组询问对于标号[1,2]的用户喜好值为1的用户的个数是1
第二组询问对于标号[2,4]的用户喜好值为5的用户的个数是0
第三组询问对于标号[3,5]的用户喜好值为3的用户的个数是2

 

链接:https://www.nowcoder.com/questionTerminal/7aa6e186a50b4ac5875eda5f924b9bdb?toCommentId=3184237
来源:牛客网

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
using namespace std;
 
int main() {
    int n,q,x;
    cin >> n;   
    map<int, vector<int>> map;
    for (int i = 1; i <= n; i++)
    {
        cin >> x;
        map[x].push_back(i);
    }
    cin >> q;
    int l, r, k;
    for (int i = 0; i < q; i++)
    {
        cin >> l >> r >> k;
        int cnt = 0;
        vector<int> list = map[k];
        for (int j = 0; j < list.size(); j++)
        {
            if (list[j] <= r && list[j] >= l)
                cnt++;
        }
        cout << cnt << endl;
    }
    system("pause");
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值