Toyota Programming Contest 2024#7(AtCoder Beginner Contest 362)

A题:Buy a Pen

思路:

大水题

code:

inline void solve() {
     int r, g, b; cin >> r >> g >> b;
     string s; cin >> s;
     int ans;
     if (s[0] == 'R') ans = min(g, b);
     else if (s[0] == 'G') ans = min(r, b);
     else ans = min(r, g);
     cout << ans << endl;
	 return;
}

B题:Right Triangle 

思路:

垂直两边内积为0

code:

inline void solve() {
     vector<PII> a(3);
     for (int i = 0; i < 3; i ++ ) cin >> a[i].first >> a[i].second;
     function<bool(PII, PII, PII)> check = [&](PII a, PII b, PII c) {
     	PII ab = {b.first - a.first, b.second - a.second};
     	PII ac = {c.first - a.first, c.second - a.second};
     	if (ab.first * ac.first + ab.second * ac.second == 0) return true;
     	return false;
     };
     for (int i = 0; i < 3; i ++ ) {
     	if (check(a[i], a[(i + 1) % 3], a[(i + 2) % 3])) return cout << "Yes\n", void();
     }
     cout << "No\n";
	 return;
}

C题:Sum = 0 

思路:

每个选取的x都有一个范围,那么其总和就有一个范围[l, r]。

显然地,对于l > 0,或者 r < 0 答案是肯定不存在的,否则就存在

那么我们可令所有xi先为最小,然后加上差值即可。

code:

inline void solve() {
     int n; cin >> n;
     vector<PLL> a(n + 1);
     ll l = 0, r = 0;
     for (int i = 1; i <= n; i ++ ) {
     	cin >> a[i].first >> a[i].second;
     	l += a[i].first, r += a[i].second;
     }
     if (l > 0 || r < 0) return cout << "No\n", void();
     ll d = -l;
     cout << "Yes\n";
     for (int i = 1; i <= n; i ++ ) {
     	ll minv = min(d, a[i].second - a[i].first);
     	d -= minv, a[i].first += minv;
     	cout << a[i].first << " \n"[i == n];
     }
	 return;
}

D题:Shortest Path 3 

思路:

思路就是题目... shortest path

我们利用优先队列优化的dij最短路即可。

不会点这 -- > 优先队列优化最短路

code:

struct edge {
	int v, w;
};
struct node {
	ll dis, u;
	bool operator > (const node& a) const {return dis > a.dis;}
};
inline void solve() {
     int n, m; cin >> n >> m;
     vector<int> a(n + 1);
     for (int i = 1; i <= n; i ++ ) cin >> a[i];
     vector<vector<edge>> e(n + 1);
     for (int i = 1; i <= m; i ++ ) {
     	int u, v, c; cin >> u >> v >> c;
     	e[u].push_back({v, c}), e[v].push_back({u, c});
     }
     vector<ll> dis(n + 1);
     for (int i = 1; i <= n; i ++ ) dis[i] = 1e18;
     vector<bool> vis(n + 1);
     priority_queue<node, vector<node>, greater<node>> q;
     dis[1] = a[1];
     q.push({a[1], 1});
     while (q.size()) {
     	int u = q.top().u; q.pop();
     	if (vis[u]) continue;
     	vis[u] = 1;
     	for (auto ed : e[u]) {
     		int v = ed.v, w = ed.w;
     		if (dis[v] > dis[u] + w + a[v]) {
     			dis[v] = dis[u] + w + a[v];
     			q.push({dis[v], v});
     		}
     	}
     }
     for (int i = 2; i <= n; i ++ ) cout << dis[i] << ' ';
	 return;
}

 E题:Count Arithmetic Subsequences

思路:

arithmetic sequences 等差子序列

我们定义dp[j][i][k] 为a[i]结尾,公差为 a[i] - a[j] 的大小为k的子序列的数量

这样我们从左到右遍历i的时候,对于一个新的a[i],我们去i的前面找一个j,这样我们就得到了一个公差,再去j的前面找一个k,那么我们就可以知道对于a[i]可以衔接在哪个以a[k]结尾的公差相同的子序列后面了。

code:

int dp[81][81][81];
inline void solve() {
	 mod = 998244353;
     int n; cin >> n;
     vector<int> a(n + 1), ans(n + 1);
     for (int i = 1; i <= n; i ++ ) cin >> a[i];
     for (int i = 1; i <= n; i ++ ) {
     	dp[0][i][1] = 1;
     	for (int j = 1; j < n; j ++ ) {
     		dp[j][i][2] = 1;
     		for (int k = 1; k < j; k ++ ) {
     			if (a[i] - a[j] == a[j] - a[k]) {
     				for (int l = 1; l <= j; l ++ ) {
     					dp[j][i][l + 1] = (dp[j][i][l + 1] + dp[k][j][l]) % mod;
     				}
     			}
     		}
     	}
     }
     for (int i = 1; i <= n; i ++ ) {
     	for (int j = 0; j < i; j ++ ) {
     		for (int k = 1; k <= i; k ++ ) {
     			ans[k] = (ans[k] + dp[j][i][k]) % mod;
     		}
     	}
     }
     for (int i = 1; i <= n; i ++ ) cout << ans[i] << " \n"[i == n];
	 return;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值