CF题目心得&总结

CF思维题心得&总结

created: 10/18/2021

updated: 10/20/2021 11/27/2021

1583B Omkar and Heavenly Tree

题意

​ t组数据,n个点,m条限制,每条限制输入a、b、c,要求建立的树在a和c之间只有一条路径并且b不在这条路径上。

​ 答案输出树的每条边相邻两点。

思路点

通过观察数据范围m < n,得出一定有一个点没有被限制,然后以这个点为中心连一个树就可以,输出每一条边。

赛中想到的

​ 以一个点为中心连边,每次将不同的点塞在b的两侧,达到了第一层,正解在第n层

Solution

#include<iostream> #include<cstring> #include<map> using namespace std; // 从点和边的数据范围中观察出技巧 int main(){ int T; scanf("%d", &T); while(T--){ int n, m; scanf("%d%d", &n, &m); map<int, int> mp; for(int i = 0; i < m; i++){ int a, b, c; scanf("%d%d%d", &a, &b, &c); mp[b] ++; } int center = 0; for(int i = 1; i <= n; i++){ if(!mp.count(i)){ center = i; break; } } for(int i = 1; i <= n; i++){ if(center == i) continue; printf("%d %d\n", i, center); } } return 0; }

1594C Make Them Equal

题意

t组数据,输入长度为n的字符串s和一个字符c,可以进行一个操作,对于1xn,可以将不能整除xi(1in),所在的下标字符替换成c,问最少经过多少次操作可以使s每个字符都是c

思路点

  • 由整除出发,
    • 对于x=n而言,1in1都可以被替换。
    • 对于x=n1i=n可以被替换。
  • 因此最多需要2次操作就可以将s替换成想要的字符串。
  • 对于做0次操作,遍历数组就行。
  • 对于做1次操作,当数组中i<nii的倍数下标位置的字符都是c的话,只需要一次操作就可以把s都替换成c,输出i的下标。
  • 对于做2次操作,就是i<nii的倍数下标位置的字符都是c,输出n1n

赛中想到的

​ 上述的第一点想到了,但是忽略了做1次操作的做法,也是这道题的核心,由第1点衍生出,i可以替换不是它倍数的下标位置(其实就是题意)。我太蠢了

Solution

#include<iostream> #include<cstring> using namespace std; int main(){ int T; scanf("%d", &T); while(T--){ int n; char c; string s; cin >> n >> c; cin >> s; bool flag = true; for(int i = 0; i < n; i++){ if(s[i] != c){ flag = false; break; } } if(flag){ printf("0\n"); continue; } bool f = false; for(int i = 1; i <= n; i++){ flag = true; for(int j = i; j <= n; j += i){ if(s[j - 1] != c){ flag = false; break; } } if(flag){ f = true; printf("1\n%d\n", i); break; } } if(!f){ // 1-n-1不存在能代替所有字符的位置 printf("2\n%d %d\n", n - 1, n); } } return 0; }

1593D2 Hall of Same

题意

D1的加强版,赛中过了,这里就不再单独将D1列出来。D1题意是输入一个数组 $a(-1e6≤a_i≤1e6) n(4≤n≤40,n为偶数)$求出一个最大的整数 k,对每个元素减去若干个 k 之后,a中所有元素相同。

​ 此题(D2)的题意与D1大致相同,但求一个最大的 k,使得数组中至少一半的元素能够相同。

思路点

  • 两道题答案所包含的元素组成的子数组中,设最小值为 v,不难发现,其他元素与v的差值(设为d )一定都对%k 同余。(应该这么表示吧?
  • 由上一点可知,k 一定是所有 d 的最大公约数
  • D1可以求出最小元素 v,再求其他元素相应的 d,D2需要观察数据范围,采用暴力枚举所有元素为 v,再筛选出其他满足条件的 d0,存取所有 d 的约数,找出大于等于 n2 的最大的那个。

赛中想到的

​ 所有 d%k 同余想到了,还是没深入思考到 k 一定是所有 d 的最大公约数。

Solution

#include<iostream> #include<set> #include<vector> #include<algorithm> #include<map> using namespace std; int main(){ int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); int a[45]; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); int ans = -1; for(int i = 1; i <= n; i++){ int v = a[i]; vector<int> nums; int same = 0; for(int j = 1; j <= n; j++){ int d = a[j] - v; if(d == 0) same++; if(d > 0) nums.push_back(d); } if(same >= n / 2){ ans = INT_MAX; continue; } map<int, int> s; for(int j = 0; j < nums.size(); j++){ int & d = nums[j]; for(int g = 1; g <= d / g; g++){ if(d % g == 0){ s[g]++; if(d / g != g) s[d / g]++; } } } for(auto t: s){ if(t.second >= n / 2 - same){ ans = max(ans, t.first); } } } if(ans == INT_MAX) ans = -1; printf("%d\n", ans); } return 0; }

1593B Make it Divisible by 25

题意

​ 多测,输入数字 n(n1e18),每次可以对 n 进行操作,删去一位数字,使 n 可以整除 25, 求最少的操作次数 ans0数据保证一定有解

思路点

  • 一个数可以被 25 整除,其后个位和十位可以是 00255075 这四种情况,根据个位为 50,分类讨论就可以了(这场ACD1E都做了,B居然没写)

赛中

脑子糊了

Solution

#include<iostream> #include<cstring> using namespace std; int main(){ int T; scanf("%d", &T); while(T--){ string s; cin >> s; int n = s.size(); // 25 75 int ans1 = 0; // 50 00 int ans2 = 0; bool flag = false; for(int i = s.size() - 1; i >= 0; i--){ if(s[i] != '5') ans1++; else{ for(int j = i - 1; j >= 0; j--){ if(s[j] == '2' || s[j] == '7'){ flag = true; break; } else ans1++; } } if(flag) break; } flag = false; for(int i = s.size() - 1; i >= 0; i--){ if(s[i] != '0') ans2++; else{ for(int j = i - 1; j >= 0; j--){ if(s[j] == '0' || s[j] == '5'){ flag = true; break; } else ans2++; } } if(flag) break; } printf("%d\n", min(ans1, ans2)); } return 0; }

1614C Divan and bitwise operations

题意

求出未知数组的所有子序列的 XOR 和,输入子序列开始位置和结束位置以及子序列的 OR 和,且保证输入包含数组每个元素。

思路点

结论题,答案为 ans2n1ans 为数组元素 OR 的和,

  • 所有子序列的 XOR 和,先由 XOR 的性质,考虑单个位,在子序列中,这个位是 1 的元素个数是偶数,那么这个位上子序列的 XOR 和为 0,反之要将这个位的结果算入答案中。

  • 将整个数组分为该位为 1 的集合 A, 和为 0 的集合 B,那么由上点可知,想选出答案,就要在 A 中选出奇数个元素,在 B 中选取的方案总和为 2|B| 个,在 A 中选奇数个数,无论 |A| 是奇数还是偶数,选取的方案数为 2|A|1=C|A|1+C|A|3++C|A|nk(|A|%2=0,k=1)

  • 因此,扩展到所有的位为 1 的情况,答案就是ans2|B|×2|A|1=ans2n1

赛中

求所有元素 ORans 是知道的。结论实在推不出来,还把题输出给读错了,以为还要输出原数组,难上加难。

Solution

#include<iostream> #include<set> typedef long long ll; typedef std::pair<int, int> PII; typedef std::pair<ll, ll> PLL; #define pb push_back using namespace std; const int mod = 1e9 + 7; template<class type> type qmi(type a, type k, type p){ type res = 1; while(k){ if(k & 1) res = 1ll * res * a % p; a = 1ll * a * a % p; k >>= 1; } return res; } int main(){ int T; cin >> T; while(T--){ int n, m; cin >> n >> m; ll res = 0; while(m--){ int l, r, x; cin >> l >> r >> x; res |= x; } cout << 1ll * res * qmi<ll>(2, n - 1, mod) % mod << endl; } return 0; }

__EOF__

本文作者Roshin
本文链接https://www.cnblogs.com/Roshin/p/CodeforcesNotes.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Roshin  阅读(195)  评论(2编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
-->
点击右上角即可分享
微信分享提示