A 小竹与妈妈

签到题

时间复杂度:O(1)

代码:

#include <bits/stdc++.h>
using namespace std;



int main() {
	int a, b, x;
	cin >> a >> b >> x;
	x -= b;
	cout << x / a << endl;
	
	
	return 0;
} 

B 走丢的小竹

签到题:

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
int a[N];

int main() {
	int n, m, q;
	cin >> n >> m >> q;
	
	for (int i = 1; i <= n; i ++ ) {
		int x;
		cin >> x;
		a[x] ++ ;
	}
	
	while (q -- ) {
		int x;
		cin >> x;
		
		cout << n - a[x] << endl;
	}
	
	
	
	return 0;
}

C 小竹关禁闭

题意:

给定一个数组,你可以选择其中的一些用来组成绳子,但是当你选择了第i个是,后面的k个将无法被选择,问你所能组

成的绳子的最长长度是多少

思路:

一眼dp题

在前k + 1个中选择时,由于他们没有前继状态用来过渡,所以他们初始化为a[i],并以此选择出最大的

k + 1个之后的话,对于每个点就会有两种状态,选/不选

两种状态分别对应这f[i - 1]和f[i - (k + 1)] + a[i]得到最大值即可

集合表示:f[i]表示从前i个中选择所能组成的最大长度
集合属性:MAX
状态转移:i <= k + 1, f[i] = max(f[i], f[i - 1])
i > k + 1, f[i] = max(f[i - 1], f[i - (k + 1)] + a[i])

时间复杂度:O(n)

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e3 + 5;
int a[N];
LL f[N];

int main() {
	int n, k;
	scanf("%d%d", &n, &k);
	
	for (int i = 1; i <= n; i ++ ) {
		cin >> a[i];
		
		if(i <= k + 1) f[i] = a[i];
	} 
	
	for (int i = 1; i <= n; i ++ ) {
		f[i] = max(f[i], f[i - 1]);
		
		if(i > k + 1) f[i] = max(f[i], f[i - (k + 1)] + a[i]);
	} 
	
	cout << f[n] << endl;
	
	return 0;
}

D 游戏购买

题意:

在给定的一个n * m的矩阵中,每个位置不是商店就是住宅,现在你需要从你自己家出发到小胖家,路途中需要买一个

刺激值大于x的游戏,(住宅不可走,商店可以走,并且每个商店可以重复经过),问中间经历的最短路径是多少?

思路 :

这个题的时间限制是5秒,所以直接跑图就可以,从起点和终点分别bfs跑图,最后找到最短的距离

时间复杂度:时间限制很小,都可以过

代码:(直接暴力写,没有任何看点)

#include <bits/stdc++.h>
using namespace std;;

#define inf 0x3f3f3f3f
typedef pair<int, int> PII;

const int N = 2e3 + 5;
int a[N][N];
int dis1[N][N];
int dis2[N][N];
int ans = 0;
PII q[N * N];
bool vis1[N][N];
bool vis2[N][N];
int n, m, x;

int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};

void bfs1(int x, int y) {
	queue<PII> qq;
	qq.push({x, y});
	vis1[x][y] = true;
	
	while (qq.size()) {
		auto temp = qq.front();
		qq.pop();
		
		int xx = temp.first;
		int yy = temp.second;
		
		for (int k = 0; k < 4; k ++ ) {
			int i = xx + dx[k];
			int j = yy + dy[k];
			
			if(a[i][j] == -1 || vis1[i][j]) continue;
			
			if(i < 1 || i > n || j < 1 || j > m) continue;
			
			dis1[i][j] = dis1[xx][yy] + 1;
			qq.push({i, j});
			vis1[i][j] = true;
		}
	}
	
}

void bfs2(int x, int y) {
	queue<PII> qq;
	qq.push({x, y});
	vis2[x][y] = true;
	
	while (qq.size()) {
		auto temp = qq.front();
		qq.pop();
		
		int xx = temp.first;
		int yy = temp.second;
		
		for (int k = 0; k < 4; k ++ ) {
			int i = xx + dx[k];
			int j = yy + dy[k];
			
			if(a[i][j] == -1 || vis2[i][j]) continue;
			
			if(i < 1 || i > n || j < 1 || j > m) continue;
			
			dis2[i][j] = dis2[xx][yy] + 1;
			qq.push({i, j});
			vis2[i][j] = true;
		}
	}
	
}

int main() {
	cin >> n >> m >> x;
	
	int a1, b1, a2, b2;
	cin >> a1 >> b1 >> a2 >> b2;
	
	for (int i = 1; i <= n; i ++ ) {
		for (int j = 1; j <= m; j ++) {
			cin >> a[i][j];
			
			if(a[i][j] > x) {
				q[ ++ ans] = {i, j};
			}
		}
	} 
	
	bfs1(a1, b1);
	bfs2(a2, b2);
	
	int res = inf;
	for (int i = 1; i <= ans; i ++ ) {
		int xx = q[i].first, yy = q[i].second;
		
		if(dis1[xx][yy] == 0 || dis2[xx][yy] == 0) continue;
		
		res = min(res, dis1[xx][yy] + dis2[xx][yy]);
	}
	
	if(res == inf) cout << "-1" << "\n";
	else cout << res << "\n";

	
	
	
	
	return 0;
}

E 寻找小竹

题意:

给定n个路口,n - 1个道路,每个路口都有一个优美值,若是有一对相邻的道路优雅值存在至少两个质因子p和q (p

!= q),则这两个路口就是共同优雅,问:整个城市的最大优雅联通块包含多少个路口

思路:

思路1:如何判断两个数是否有两个不同的公共质因子:

    求出gcd,看gcd分解形式是否有两个不同的质因子

    如何快速做,预处理每个数的随意的一个之因子(用于分解gcd,这里需要知道对于每个数都会存在一个质因子)

思路2:如何得到最终的答案,树形dp,并查集

参考视频:https://www.bilibili.com/video/BV1NP411c7TM/?p=4&vd_source=12435eebd609bf864d269dac69151858

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 5e6 + 5;
int a[N];
bool vis[N];
int ans[N];//记录每个连通块的大小
int mnp[N];
int n;
vector<int> e[N];

void init() {
        //预处理出范围内的所有的是的一个质因子,用于分解gcd
	for (int i = 2; i <= 5000000; i ++ ) {
		if(vis[i]) continue;
		
		mnp[i] = i;
		//特别注意这里会爆int
		for (LL j = (LL)i * i; j <= 5000000; j += i) {
			vis[j] = 1;
			mnp[j] = i;
		}
	}
}

int gcd(int a, int b) {
	if(b == 0) return a;
	return gcd(b, a % b);
}

//判断两者是否具有公共质因子
bool ok(int a, int b) {
	int g = gcd(a, b);
	vector<int> v;
	while (g != 1) {
		int mn = mnp[g];
		v.push_back(mnp[g]);//素数因子 
		while (g % mn == 0) g /= mn;
	}
	
	return v.size() >= 2;
}

//通过dfs寻找每个点
void dfs(int u, int fa) {
	for (auto x : e[u]) {
		if(x == fa) continue;
		dfs(x, u);
		if(ok(a[x], a[u])) ans[u] += ans[x];
	}
}

int main() {
	init();
	
	cin >> n;

	for (int i = 1; i <= n; i ++ ) {
		cin >> a[i];
		ans[i] = 1;
	}
	
	for (int i = 1; i < n; i ++ ) {
		int u, v;
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	
	dfs(1, -1);
	
	int res = 1;
	for (int i = 1; i <= n; i ++) {
		res = max(res, ans[i]);
	}
	
	cout << res << endl;
	
	
	
	return 0;
}
posted on 2022-11-12 16:19  知白-剑仙  阅读(44)  评论(0)    收藏  举报