标签:模拟 绝对值 cli syn 生成 median 初始 需要 contest
本场Div3非常适合训练思维和手速。因为真的不算难,是我完整补完所有题目的一场CF了。
题意:
给出两块长度为a,宽度为b的矩阵,矩阵可以旋转自由拼接,但是两块矩阵不能相交,求能覆盖这两个矩阵的最小正方形面积。
思路:
仔细思考只有把矩阵的最长边固定,再把两个矩阵的短边拼在一块才会是最优的。简单证明一下 设a为长边 b为短边,那么拼接后只会有 三种可能 a + a , a + b, b + b。而影响正方形边长的因素是那个最长的边。即是 max(a, a + a, a + b, b + b),显然要让这个尽量小的话就把 a + a, a + b 去掉只比较 a和 b + b.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int t; 5 6 int main(){ 7 cin >> t; 8 while(t--){ 9 int a, b; 10 cin >> a >> b; 11 int Now = min(a, b) + min(a, b); 12 Now = max(Now, max(a, b)); 13 cout << Now * Now << endl; 14 } 15 return 0; 16 }
题意:
把n个数分成两组,让第一组的最大值 与 第二组的最小值的差 的绝对值最小。
思路:
思考一下就是把n个数排序,之后枚举切割点(在此把所有数分成两段,并且左端的最大值与右端的最小值是相邻的)。
#include <bits/stdc++.h> using namespace std; int t; int n; int s[1005]; int main(){ cin >> t; while(t--){ cin >> n; for(int i = 1; i <= n; i++) cin >> s[i]; sort(s + 1, s + 1 + n); int Min = 0x3f3f3f; for(int i = 2; i <= n; i++) Min = min(Min, abs(s[i] - s[i - 1])); cout << Min << endl; } return 0; }
题意:
如果两个数有相同的奇偶性、或者两个数之差的绝对值为1,则称两个数是相似的。给出n个数,求是否将这n个数划分成n/2对相似的数。
思路:
题意:
给出两个数n,k。你需要选择0~k之间的一个数,使其加和t次后恰好为n。 求t的最小值是多少?
思路:
显然我们要找的是n的因数p,同时要求t尽量小,所以这个p要尽量大。于是我们枚举n的因数t从1~根号n,同时这样意味着我们选择的是p是n / i,但必须保证这个 n / i值在k的范围内,否则p选择i,则t为n / i.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 int t; 7 ll n, k; 8 9 int main(){ 10 cin >> t; 11 while(t--){ 12 cin >> n >> k; 13 if(k >= n) cout << 1 << endl; 14 else{ 15 ll Out = 1e9; 16 for(ll i = 1; i * i <= n && i <= k; i++){ 17 if(n % i == 0){ 18 if(n / i <= k) Out = min(Out, i); 19 else Out = min(Out, n / i); 20 } 21 } 22 cout << Out << endl; 23 } 24 } 25 return 0; 26 }
题意:
一个n*n的格子,左侧和上侧各有n个炮台,初始阶段所有格子为0,每次炮台都可以发射一颗数字为1的炮弹,炮弹触及到边界或者格子数为1时停止并在当前格子生成1.给定了一个目标的状态,询问是否能通过这2n个炮台按照一定顺序发射炮弹来完成。
思路:
根据观察我们会发现,如果一个格子是1并且相邻的右格子和下面格子都为0的话,并且不是在边界上的格子的话。那么一定是不可行的。
#include <bits/stdc++.h> using namespace std; int t; int n; char aim[55][55]; int main(){ scanf("%d", &t); while(t--){ scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%s", aim[i] + 1); } bool Can = true; for(int i = 1; i < n; i++) for(int j = 1; j < n; j++) if(aim[i][j] == ‘1‘ && aim[i+1][j] == ‘0‘ && aim[i][j+1] == ‘0‘ ) Can = false; if(Can) puts("YES"); else puts("NO"); } return 0; }
题意:
思路:
题意:
思路:
题意:
一共有2^m个长度为m的二进制字符串,按照从小到大的顺序排列。 例如m=3则按照 000 001 010 011 100 101 110 111排列。要求在删去n个二进制串后,输出第(k-1)/2个二进制串。 其中 1 <= n <= min(2 ^ m - 1, 100) 并且 m <= 60 k = 2 ^ m - n
思路:
观察样例,会发现如果删去的x(x<=n) 个二进制串在第 (k-1)/2 之后的话,不会产生任何影响。如果这删除的x个串在第 (k-1)/2 之前的话,那么就从第 (k-1)/2 位置开始后移X个位置。 (手动模拟一下样例会更好) 因为最多不超过100个n,所以最多移动100位,不会超时。
还有记得输入和输出的问题!
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; int t; ull Del[111]; int main(){ ios::sync_with_stdio(false); cin >> t; while(t--){ int n, m; memset(Del, 0, sizeof(Del)); cin >> n >> m; for(int i = 0; i < n; i++){ string x; cin >> x; reverse(x.begin(), x.end()); ull now = 1; for(int j = 0; j < x.length(); j++){ if(x[j] == ‘1‘) Del[i] += now; now <<= 1; } } sort(Del, Del + n); ull k = pow(2, m) - n; ull Num = (k - 1) / 2; for(int i = 0; i < n; i++){ if(Num >= Del[i]) Num ++; else break; } //cout << "Num : " << Num << endl; string ans; while(Num > 0){ if(Num % 2 == 0) ans += "0"; else ans += "1"; Num >>= 1; } for(int i = m; i >= ans.length() + 1; i--) cout << 0; for(int i = ans.length() - 1; i >= 0; i--) cout << ans[i]; cout << endl; } return 0; }
Codeforces Round #644(Div.3) 题解
标签:模拟 绝对值 cli syn 生成 median 初始 需要 contest
原文地址:https://www.cnblogs.com/LYFer233/p/13081371.html