Codeforces Round #599A~D题解
程序员文章站
2022-05-04 16:25:59
...
Maximum Square
这是一道很简单的题目大意就是说给你一个几个木棍拼成一串问你从中扣出一个正方形的最大边长是多少
二分简单枚举一下可能的长度再判断一下就好了
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e3 + 10;
int k, T;
int a[N];
bool check(int mx)
{
int ans = 0;
for(int i = 0; i < k; ++ i)
if(a[i] >= mx) ans ++;
if(ans >= mx) return true;
else return false;
}
int ans()
{
int l = 0, r = k;
while(l < r)
{
int mid = (l + r + 1 )>> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
return r;
}
int main()
{
cin >> T;
while(T --)
{
cin >> k;
for(int i = 0; i < k; ++ i)
cin >> a[i];
sort(a, a + k);
cout << ans() << endl;
}
}
Character Swap (Easy Version)
题目大意就是说给你两个字符经过一次交换两个字符串中的任意位置的字母后是否可以达到相同
1.如果不是两个位置不一样一定是no
2,如果两个位置不一样但是字母不是对应相同就no否则就是Yes
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e4 + 10;
int T, n;
char ch[N];
char a[N];
int ma[N];//记录不相同点的位置
int num, k;
int main()
{
cin >> T;
while(T --)
{
num = 0;
k = 0;
cin >> n;
for(int i = 0; i < n; ++ i)
cin >> a[i];
for(int i = 0; i < n; ++ i)
{
cin >> ch[i];
if(ch[i] != a[i]) num ++, ma[k ++] = i;
}
if(num == 2)
{
if(a[ma[0]] == a[ma[1]] && ch[ma[0]] == ch[ma[1]])
cout << "Yes" << endl;
else cout << "No" << endl;
}
else cout <<"No" << endl;
}
return 0;
}
跟easy部分有点不同就是说你可以最多交换2 * n次之后是否相同可以达到相同如果可以就输出交换的过程
解题思路:
1.首先判断一下两个串中的字母出现的次数是否是偶数次
2.如果是我们简单模拟一下先将第一列对其再将第二列对其以此类推因为字符串的长度才50所以模拟是可以过的
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
const int N = 1e4 + 10;
int T, n, num;
int vis[N];
char ch[N],a[N];
bool flag;
PII p[N];//用pair记录交换路径
int main()
{
std::ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
cin >> T;
while(T --)
{
flag = true;
num = 0;
cin >> n;
for(int i = 0; i < n; ++ i)
{
cin >> a[i];
vis[a[i] - 'a'] ++;
}
for(int i = 0; i < n; ++ i)
{
cin >> ch[i];
vis[ch[i] - 'a'] ++;
}
for(int i = 0; i < 26 && flag; ++ i)
if(vis[i] % 2)//进行第一步
{
cout <<"No" << endl;
flag = false;
}
//...................................................................
memset(vis,0,sizeof(vis));
if(!flag) continue;
int id;
for(int i = 0; i < n; ++ i)
//首先枚举第一行的字符串
{
flag = false;
id = i + 1;
if(a[i] == a[i + 1] && ch[i] == ch[i + 1])
{
if(a[i] != ch[i])
p[num ++] = {i,i + 1};
i ++;
continue;
}
//因为你的匹配字符串的可能是在原串也可能在下面
for(int j = i; j < n; ++ j)
{
if(a[i] == ch[j] && j == i)
{
flag = true;
break;
}
if(a[i] == ch[j])
{
while(a[id] == ch[id]) id ++;//模拟一下找到右边第一个不对齐的点将其交换
swap(a[id],ch[j]);
p[num ++] = {id,j};
swap(ch[i],a[id]);
p[num ++] = {id,i};
flag = true;
break;
}
}
if(!flag)
for(int k = i + 1; k < n; ++ k)
if(a[i] == a[k] && a[k] != ch[k])
{
swap(a[k],ch[i]);
p[num ++] = {k,i};
}
}
//...................................................................
if(num > 2 * n) cout << "No" << endl;
else
{
cout << "Yes" << endl;
cout << num << endl;
for(int i = 0; i < num; ++ i)
cout << p[i].first + 1<< " " << p[i].second + 1<< endl;
}
}
cout.flush();
return 0;
}
Tile Painting
一道数学题其实自己手动模拟一下可以找到规律
给你一个长度为n的路径,路径有一个个小方格,就是说n % (i - j) == 0 && i - j > 1 的i 和 j的方格涂相同的颜色,问你最多涂多少种颜色
解题思路:
1.因为n’%(i - j) == 0 所以i - j 就是n的因子
2.将n分解质因子
3.那么循环节是多少呢 lcm(所有的质因子)= n
4.那么循环长度就是 n / lcm == 1;
我们还有处理一下质因子只有一个的情况
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
LL n, m;
int main()
{
cin >> n;
if(n == 1)
{
cout << "1" << endl;
return 0;
}
for(LL i = 2; i * i * 1ll <= n; ++ i)
if(n % i == 0)
{
ans.push_back(i);
while(n % i == 0) n /= i;
}
if(n > 1) ans.push_back(n);
if(ans.size() == 1) cout << ans.back() << endl;
else cout << "1" << endl;
return 0;
}
0-1 MST
如果数据范围小的话就是一道最小生成树的裸题但是数据范围比较大所以我们要用dfs模拟克鲁斯卡尔算法
因为边权只有1和0这两个数字所以对于边权没有1的点我们可以看成一个·点就是缩点缩
点 因为根据克鲁斯卡尔的算法思路就是如果两个点边权有0之后一定会选择0这条边去连接 再去求联通块的数目就好 再减一就是答案(最小生成树边个数 = 点个数 - 1
#include <iostream>
#include <set>
#include <vector>
using namespace std;
const int N = 1e5 + 10;
bool u[N];
set<int> g[N];
set<int> vis;
void dfs(int x)
{
u[x] = 1;//标记访问
vis.erase(x);
vector<int> ret;
for(auto p : vis)
if(!g[x].count(p))
ret.push_back(p);
for(int i : ret)
vis.erase(i);
for(int t : ret)
{
u[t] = 1;
dfs(t);
}
}
int main()
{
int n, m;
cin >> n >> m;
for(int i = 0; i < m; ++ i)
{
int x, y;
cin >> x >> y;
x --, y --;//把边权有1的点删掉
g[x].insert(y);
g[y].insert(x);
}
for(int i = 0; i < n; ++ i)//表示有哪些点没有被访问过
vis.insert(i);
int ans = 0;
for(int i = 0; i < n; ++ i)
if(!u[i])
{
ans ++;
dfs(i);
}
cout << ans - 1 << endl;
return 0;
}
推荐阅读
-
Codeforces Round #656 (Div. 3)D. a-Good String(递归+dfs)
-
Codeforces Global Round 9(A~D题解)
-
Educational Codeforces Round 97 (Rated for Div. 2) D. Minimal Height Tree
-
Codeforces Round #665 (Div. 2) D. Maximum Distributed Tree(dfs)
-
【Codeforces Global Round 7】A. Bad Ugly Numbers 题解
-
构造思维+树形结构 Codeforces Round #612 (Div. 2) D题 Numbers on Tree
-
Codeforces Round #619 (Div. 2) D. Time to Run
-
Codeforces Round #674 D.Non-zero Segments【前缀和 | set】
-
Codeforces Round #659 (Div. 2) 题解
-
Codeforces Round #583 (Div. 1 + Div. 2,) D. Treasure Island(dfs+思维)