USACO 1.4.4 密码锁

1.4.4 密码锁

题目考查

暴力 容斥原理 环形距离

解题思路

首先我们比较容易的想出一个 O ( n 3 ) O(n^3) O(n3)的暴力方式, 枚举每一种情况, 分别判断是否合法即可. 对于通过本题是足够的.


但对于这题, 我们有一种更好的 O ( 1 ) O(1) O(1)方式求解.
容斥原理, 我们可以先计算出对于每一组密码合法的总情况数量, 然后再减去二者同时合法的情况.
其中某组密码合法的情况 = min(5, n) * min(5, n) * min(5, n).

假设 n ≥ 5 n \ge 5 n5, 考虑到对于两个密码而言, 如果当前位最小距离差 d i s dis dis, 则会有 5 − d i s 5 - dis 5dis种重复情况.

例如:
9
1 5 9
2 8 7

那么两个密码第一位重复的数字有: 9, 1, 2, 3 共4种
两个密码第二位重复的数字有: 6, 7 共2种
两个密码第三位重复的数字有: 7, 8, 9 共3种

因此总的重复情况为: 4 ∗ 2 ∗ 3 4 * 2 * 3 423种.

如果n < 5的情况, 那么实际上只有一组密码产生了贡献. 我们直接减去 n ∗ n ∗ n n * n * n nnn即可.


对于本题, 我们还需要会求两个数字的最小环形距离.

我们发现对于数字 x , y x, y x,y, 二者的距离无非是: ∣ x − y ∣ |x - y| xy n − ∣ x − y ∣ n - |x - y| nxy.

题目细节

AC代码

容斥原理: O ( 1 ) O(1) O(1)
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
int a[5], b[5];
int main()
{
    int n; cin >> n;
    rep(i, 3) cin >> a[i]; rep(i, 3) cin >> b[i];

    int res = 2 * min(5, n) * min(5, n) * min(5, n);

    if (n >= 5) {
    	int qaq = 1;
		rep(i, 3) {
			int dis = min(abs(a[i] - b[i]), n - abs(a[i] - b[i]));
			qaq *= max(5 - dis, 0);
		}
		res -= qaq;
    }
    else res -= n * n * n;

    cout << res << endl;

    return 0;
}

暴力: O ( n 3 ) O(n^3) O(n3)
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
int n;
int a[5], b[5], c[5];
bool fact() {
	bool flaga = 1, flagb = 1;
	rep(i, 3) {
		int disa = min(abs(c[i] - a[i]), n - abs(c[i] - a[i]));
		int disb = min(abs(c[i] - b[i]), n - abs(c[i] - b[i]));
		if (disa > 2) flaga = 0;
		if (disb > 2) flagb = 0;
	}
	return flaga | flagb;
}
int main()
{
	cin >> n;
	rep(i, 3) cin >> a[i]; rep(i, 3) cin >> b[i];

	int res = 0;
	rep(i, n) rep(j, n) rep(k, n) {
		c[1] = i, c[2] = j, c[3] = k;
		res += fact();
	}

	cout << res << endl;

	return 0;
}

END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逍遥Fau

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

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

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

打赏作者

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

抵扣说明:

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

余额充值