2024牛客寒假训练营第一场

A.DFS搜索

简单遍历判断是否出现过即可

void solve() {
	string str;
	cin >> n;
	cin >> str;
	int s = 0, s1 = 0;
	for (int i = 0; str[i]; i++) {
		if (str[i] == 'D' && s == 0) s++;
		if (str[i] == 'F' && s == 1) s++;
		if (str[i] == 'S' && s == 2) s++;
		if (str[i] == 'd' && s1 == 0) s1++;
		if (str[i] == 'f' && s1 == 1) s1++;
		if (str[i] == 's' && s1 == 2) s1++;
	}
	if (s == 3)cout << "1 ";
	else cout << "0 ";
	if (s1 == 3) cout << "1\n";
	else cout << "0\n";
}
B.关鸡

有0,1,2,3三种情况,用map来存储,方便判断该点位上是否有火,op[1]存储第一行,op[2]存储第二行。

0:(1,0)的左右两边都存在着直接上下挨着或者角对角挨着的,无需添加

1:两边其中一边的被堵住了,另一边有火但是没有堵住

2:一边被堵住,另一边没有火

3:两边都没有火,此时只需要在(1,1)(1,-1)(2,0)加上就可以了

ll n, m, a[N], b[N], c[N], d[N];
void solve() {
	map<ll, ll>op[3];
	ll z = 0, y = 0;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i] >> b[i];
		if (b[i] < 0) z++;
		if (b[i] > 0) y++;
		if (a[i] == 1) {
			op[1][b[i]] = 1;
		}
		else {
			op[2][b[i]] = 1;
		}
	}
	ll ans = 0;
	bool tr1 = 0, tr2 = 0;
	for (auto it : op[1]) {
		ll s = it.first;
		if (op[2][s] || op[2][s - 1] || op[2][s + 1]) {
			if (s < 0) tr1 = 1;
			else tr2 = 1;
		}
	}
	if (tr1 && tr2) ans = 0;
	else if (!tr1 && !tr2) {
		if (op[2][0]) ans = 2;
		else if (op[1][1] && op[1][-1]) ans = 1;
		else if (op[1][1] || op[1][-1]) ans = 2;
		else if (z && y) ans = 2;
		else ans = 3;
	}
	else {
		if (tr1) {
			if (op[2][0]) ans = 1;
			else {
				if (y) ans = 1;
				else ans = 2;
			}
		}
		else {
			if (op[2][0]) ans = 1;
			else {
				if (z) ans = 1;
				else ans = 2;
			}
		}
	}
	cout << ans << '\n';
}
C.按闹分配

将数组a排序,从小到大就是合理安排的顺序。然后,求前缀和

二分寻找最佳插队位置,多出来的不满意度就是tc乘以鸡插队位置后面的人数,判断是否小于等于m。

ll n, q,m,tc, a[N], sum[N], s[N], d[N];
bool check(ll nb) {
	if ((n - nb) * tc <= m) return true;
	else return false;
}
void solve() {
	cin >> n >> q >> tc;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + 1 + n);
	for (int i = 1; i <= n; i++) {
		sum[i] = sum[i - 1] + a[i];
	}

	for (int i = 1; i <= q; i++) {
		cin >> m;
		ll l = -1, r = n + 1;
		while (l + 1 < r) {
			ll mid = (l + r) / 2;
			if (check(mid)) r = mid;
			else l = mid;
		}
cout << sum[r]+tc << "\n";
	}
}
E.本题又主要考察了贪心

深搜,对三种情况都进行搜索。寻找最靠前的排名即可。

ll n, m, a[N],u[N],v[N];
vector<PII> op;
ll ans = 0;
void dfs(int k) {
	if (k > m) {
		ll tol = 0;
		map<int, int>op;
		for (int i = 2; i <= n; i++) {
			if (a[i] > a[1])op[i]++;
		}
		for (auto it : op) {
			tol += it.second;
		}
		ans = min(ans, tol + 1);
		op.clear();
		return;
	}
		a[u[k]] += 3;
		dfs(k + 1);
		a[u[k]] -= 3;

		a[u[k]] += 1, a[v[k]] += 1;
		dfs(k + 1);
		a[u[k]] -= 1;
		a[v[k]] -= 1;

		a[v[k]] += 3;
		dfs(k + 1);
		a[v[k]] -= 3;
	return;
}
void solve() {
	ans = 1000;
	cin >> n>>m;
	for (int i = 1; i <= n; i++)cin >> a[i];
	for (int i = 1; i <= m; i++) {
		cin >> u[i] >> v[i];
	}
	dfs(1);
	cout << ans << "\n";

}
int main() {
	IOS;
	int t;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}
F.鸡数题

一道很裸的求第二类斯特林数题,我当时只有二维递推(O(n*m))的板子,赛时找时间复杂度低的没找到(痛哉!)

#include "bits/stdc++.h"

using namespace std;
using i64 = long long;
constexpr int P = 1000000007;

i64 *fac, *ifac;
//快速幂
i64 power(i64 a, i64 b, int p = P) {
    i64 res = 1;
    for (; b; b >>= 1, a = a * a % p) {
        if (b & 1) {
            res = res * a % p;
        }
    }
    return res;
}
//求逆元
i64 inv(i64 x) {
    return power(x, P - 2);
}
//预处理阶乘与阶乘逆元
void init(int N) {
    fac = new i64 [N + 1];
    ifac = new i64 [N + 1];
    fac[0] = 1;
    for (int i = 1; i <= N; i++) {
        fac[i] = fac[i - 1] * i % P;
    }
    ifac[N] = inv(fac[N]);
    for (int i = N - 1; i >= 0; i--) {
        ifac[i] = ifac[i + 1] * (i + 1) % P;
    }
}
//求组合数
i64 C(int n, int m) {
    if (m < 0 || m > n || n < 0) {
        return 0;
    }
    return fac[n] * ifac[m] % P * ifac[n - m] % P;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;

    init(m);

    i64 ans = 0;
    for (int k = 0; k <= m; k++) {
        if (k % 2 == 0) {
            ans = (ans + C(m, k) * power(m - k, n) % P) % P;
        } else {
            ans = (ans - C(m, k) * power(m - k, n) % P + P) % P;
        }
    }
    cout << ans * ifac[m] % P << '\n';

    return 0;
}
G.why买外卖

数据范围不大,根据a[i]进行排序,然后遍历预处理各个优惠下一共减去多少金额,随后遍历每一种优惠,取最大值。

ll n, m, a[N], b[N],c[N],d[N];
void solve() {
	vector<pair<ll, ll>>op;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i] >> b[i];
		op.push_back({ a[i],b[i] });
	}
	sort(op.begin(), op.end());
	ll s = 0,sum=0,ans=m;
	c[0] = 0, d[0] = 0;
	for (auto it : op) {
		if (it.first != d[s]) {
			d[++s] = it.first;
			c[s] = c[s - 1] + it.second;
		}
		else {
			c[s] += it.second;
		}
	}
	for (int i = 1; i <= s; i++) {
		sum = c[i] + m;
		if (sum >= d[i]) ans = max(ans, sum);
	}
	cout << ans << "\n";
}
int main() {
	IOS;
	int t;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}
I.It's bertrand paradox. Again!

第一种圆生成时不受r的限制,比较分散,第二种圆生成的x,y会比较接近50,所以比较\sum_{i=1}^{n}((Xi)^2+(Yi)^2)和50*50*2*n的大小关系就好了

int main()
{
	int n;
	cin >> n;
	int cnt1 = 0;
	ll sum1 = 0;
	ll sum2 = 50 * 50 * n * 2;
	while (n--)
	{
		int x, y, r;
		cin >> x >> y >> r;
		sum1 += x * x + y * y;
	}
	if (sum1 > sum2) cout << "bit-noob\n";
	else cout << "buaa-noob\n";
	return 0;
}
L.要有光

光源放在黑线与地面交点就是最优解,会形成一个上底为2w,下底为4w,高为c的梯形,输出其面积即可

double c, d, h, w;
void solve() {
	double ans = 0;
	cin >> c >> d >> h >> w;
		ans = 6.0 * w * c / 2;
		printf("%.5lf\n", ans);
}
int main() {
	int t;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}
M.牛客老粉才知道的秘密

n取余6等于0的话,向左向右都是相同的n/6个数字。

不等于0的话,向左向右分别是不相同的n/6个数字。

可以自行模拟一下。

ll n, a[N];
map<ll,ll>op;
void solve() {
	ll ans = 0;
	cin >> n;
	if (n % 6 == 0) ans = n / 6;
	else ans = n / 6 * 2;
	cout << ans << "\n";
}
int main() {
	IOS;
	int t;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骰子.w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值