2023杭电多校第九场 - 2 5 8 12

比赛地址:传送门
赛时过了 4 题,继续加油哈 ~

1002 思维题
1005 模拟题
1008 结论题,但是自己目前没法证明
1012 诈骗题


1002 Shortest path

题意
翻译一下题面
给你数字 1,你可以进行任意次三种操作:

  • 将数字 \(i\) 变成 \(i + 1\)
  • 将数字 \(i\) 变成 \(2 \times i\)
  • 将数字 \(i\) 变成 \(3 \times i\)

问你从数字 1 变成数字 n 的所需要的最少操作次数
$1 \le n \le 10 ^ {18} $

思路
反向考虑问题
可以很轻易地发现能用操作 2 和操作 3 是一定要使用,因为这样绝对比普通的使用操作 1来的操作次数小;当都无法使用时,可以利用操作 1 修正数字使得其可以使用操作 2 和操作 3。我们利用记忆化搜索存下反向搜索的已经到达的点到达 1 时所需要的最少次数即可出答案。
还在思考这样操作的充要性?但是我没法证明捏

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f, mod = 998244353;
ll n;
unordered_map<ll, ll> q;

int dfs(ll x){
	if(x == 1 || x == 0 || q[x]) return q[x];
	int t = min(x % 2 + dfs(x / 2) + 1, x % 3 + dfs(x / 3) + 1);
	return q[x] = t;
}

void solve(){
	cin >> n;
	q[1] = 0; q[2] = q[3] = 1;
	dfs(n);
	cout << q[n] << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}

1005 List Reshape

题意
阿巴阿巴,自己看题吧,看完就懂了

思路
模拟题意即可

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f, mod = 998244353;
string ss;
vector<int> num;

void out(int l, int r){
	cout << "[";
	for(int i = l; i <= r; ++ i){
		cout << num[i];
		if(i < r) cout << ", ";
	}
	cout << "]";
	return ;
}

void solve(){
	getchar();
	getline(cin, ss);
	num.clear();
	num.push_back(0);
	int x = 0, y;
	for(auto c : ss){
		if(c == ' ' || c == '['){
			x = 0;
			continue;
		}else if(c == ',' || c == ']'){
			num.push_back(x); x = 0;
		}else{
			x = x * 10 + c - '0';
		}
	}
	cin >> x >> y;
	cout << '[';
	for(int i = 1, j = y; i <= x * y; i += y, j += y){
		out(i, j);
		if(j == x * y) cout << "]";
		else cout << ", ";
	}
	cout << endl;
	return ;
}

signed main(){
	// ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}

1008 Coins - 不会证明qwq

题面
不记题面了,自己看题面吧~

思路
仅摘记答案
答案为 $\displaystyle \sum_{i = 1}^{n} \sum_{j = i + 1}^{n} a_i a_j $

代码

ll n, a[maxm];

inline void print(__int128_t n){
	if(n < 0){
		putchar('-');
		n*=-1;
	}
	if(n > 9) print(n / 10);
	putchar(n % 10 + '0');
}

void solve(){
	cin >> n;
	__int128_t ans = 0;
	for(int i = 0; i < n; ++ i){
		cin >> a[i];
	}
	for(int i = 0; i < n - 1; ++ i){
		ans += a[i] * a[i + 1];
		a[i + 1] += a[i];
	}
	print(ans);
	cout << '\n';
	return ;
}

1012 Inference

题意
给你 n 个人每个人的 m 个特征数据,再给你 Alice 的前 m - 1 个特征值,特征值的可能取值为0, 1, 2。请你由给出的公式(见 hdu 题面)判断 Alice 的最后一个特征值取 0,1,2 中的哪个数字的可能性最大?

思路
诈骗题!
理解题意之后可以发现,这题的难点就在读懂题面。问的是最后取哪个值的可能性最大?观察到给出的式子中,影响最终概率大小的只有式子 \(P(x_m | \pi(x_m))\),而这个就是个条件概率,所以其实这题根本用不着求概率,我们只需要统计在 n 个人中 $\pi(x_m) $ 所包含的特征值均相等的人中,\(x_m\)里 012 出现的次数,最终哪个数字出现的次数越多,那么那个就是最终的答案
表述可能不太好理解,还是看题面吧

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f, mod = 998244353;

void solve(){
	int n, m, k;
	cin >> n >> m >> k;
	vector<int> e[n + 1];
	for(int i = 0; i < k; ++ i){
		int x, y; cin >> x >> y;
		e[y].push_back(x);
	}
	int f[n + 1][m + 1];
	for(int i = 1; i <= n; ++ i){
		for(int j = 1; j <= m; ++ j){
			cin >> f[i][j];
		}
	}
	vector<int> p(m + 1);
	for(int i = 1; i < m; ++ i) cin >> p[i];
	vector<int> cnt(3, 0);
	for(int i = 1; i <= n; ++ i){
		bool flag = true;
		for(auto x : e[m]){
			if(f[i][x] != p[x]){
				flag = false; break;
			}
		}
		if(flag) ++ cnt[f[i][m]];
	}
	int ans = 0;
	if(cnt[1] > cnt[ans]) ans = 1;
	if(cnt[2] > cnt[ans]) ans = 2;
	cout << ans << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}
posted on 2023-08-15 17:13  Qiansui  阅读(70)  评论(0编辑  收藏  举报