id="c_n9"width="1920"height="990"style="position: fixed; top: 0px; left: 0px; z-index: -1; opacity: 0.5;">

codeforces 1829G. Hits Different 容斥原理+记忆化搜索

题目描述

给定一个n,把n给打倒,然后递归的求出包含n在内的上面所有的会倒下的瓶子值的平方和。

这里使用二分先求出目前给定的n的行号i和列号j。观察可以发现,对于所有的列号j,j=1或者j=i时,是需要考虑往上单边的总和,其他情况都有两个分支。

再观察可以发现,两个分支在再上一行的重合部分,会被dfs多计算一遍,所以减去这一部分即可。

把计算结果用map保存,减少重复计算。

复制代码
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define int long long
 6 
 7 map<pair<int, int>, int> mp;
 8 
 9 int dfs(int i, int j)
10 {
11     if (mp.count({i, j})) {
12         return mp[{i, j}];
13     }
14     if (j > i || j <= 0) {
15         return mp[{i, j}] = 0;
16     }
17     int s = i * (i - 1) / 2 + j;
18     if (j == 1 || j == i) {
19         return mp[{i, j}] = s * s + dfs(i - 1, j) + dfs(i - 1, j - 1);
20     } else {
21         return mp[{i, j}] = s * s + dfs(i - 1, j) + dfs(i - 1, j - 1) - dfs(i - 2, j - 1);
22     }
23 }
24 
25 void solve()
26 {
27     int n;
28     cin >> n;
29     int l = 1, r = 2023;
30     while (l < r) {
31         int mid = (l + r) >> 1;
32         if ((1 + mid) * mid / 2 >= n) {
33             r = mid;
34         } else {
35             l = mid + 1;
36         }
37     }
38     int curRow = l;
39     int curPos = n - curRow * (curRow - 1) / 2;
40     mp[{1, 1}] = 1;
41     cout << dfs(curRow, curPos) << endl;
42 
43 }
44 
45 int32_t main()
46 {
47     ios_base::sync_with_stdio(false);
48     cin.tie(nullptr); cout.tie(nullptr);
49 
50     int t = 1;
51     cin >> t;
52     while (t--) {
53         solve();
54     }
55 
56     return 0;
57 }
复制代码

 

posted @   My_opt  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示