打卡 Codeforces Round #599 (Div. 2)
A题
水题,贪心即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int k, n;
int a[1005];
int main()
{
k = read();
while (k--)
{
n = read();
upd(i, 1, n)a[i] = read();
sort(a + 1, a + 1 + n);
int wid = 0;
int hi = 0;
hi = a[n]; wid = 1;
int ans = 0;
ans = min(hi, wid);
dwd(i, n-1, 1)
{
hi = min(hi, a[i]);
wid++;
ans = max(ans,min(hi,wid));
}
printf("%d\n", ans);
}
return 0;
}
B题
继续暴力,有点冒泡排序的感觉。
只要每个字符的出现次数是偶数,那么一定可以通过某种交换使得两个字符串相等。暴力枚举和交换即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int k, n;
string s, t;
map<char, int>mp_s,mp_t,mp;
vector<int> pos[1005], pos_s[1005];
int main()
{
k = read();
while (k--)
{
n = read();
mp_s.clear(); mp_t.clear(); mp.clear();
upd(i, 0, n)pos[i].clear();
cin >> s >> t;
if (s.size() != t.size()) { cout << "no" << endl; continue; }
int cnt = 0;
for (auto p : s)mp_s[p]++,mp[p]++,pos_s[p].push_back(cnt++);
cnt = 0;
for (auto p : t)mp_t[p]++,pos[p].push_back(cnt++),mp[p]++;
bool flag = 0;
for (auto p : mp)if (p.second % 2)flag = 1;
if (flag) { printf("NO\n"); continue; }
vector<pir>ans;
up(i, 0, s.size())
{
if (s[i] != t[i])
{
bool flag = 0;
up(j, i+1, t.size())
{
if (t[j] == s[i])
{
swap(s[i + 1], t[j]);
swap(s[i + 1], t[i]);
ans.push_back(make_pair(i + 2, j+1));
ans.push_back(make_pair(i + 2, i+1));
flag = 1;
break;
}
}
if (!flag)
{
up(j, i+1, s.size())
{
if (s[j] == s[i])
{
swap(s[j], t[i]);
ans.push_back(make_pair(j+1, i+1));
break;
}
}
}
}
}
printf("YES\n");
printf("%d\n", ans.size());
//cout << s << " " << t << endl;
for (auto k : ans)printf("%d %d\n", k.first, k.second);
}
return 0;
}
C题
我们首先看有两个数字互质的情况。
由完全剩余系可以知道,如果a,b两个数字互质,a*1,a*2,a*3,...a*(b-1),a*b 模上b,可以取到1~b-1的一个permutation。
即,我们假设x染成颜色1,x+a,x+2a,x+3a....都将成为颜色1,由上述定理可知,(x+1)+b,(x+1)+b*2....肯定会由c,c=x+m*a,c=(x+1)+n*b,所以x和x+1一定会被染色成一个颜色。
我们对n进行唯一分解定理,如果有两个质数,那么答案为1。
如果只有一个质数,答案为该质数。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
ll n;
vector<ll>vec;
int main() {
n = read();
if (n == 1)
{
printf("%d\n", 1);
return 0;
}
for (ll i = 2; i*i <= n; i++)
{
while (!(n%i))
{
while (!(n%i))n /= i;
vec.push_back(i);
}
}
if (n > 1)vec.push_back(n);
if (vec.size() > 1)
{
printf("%d\n", 1);
}
else
{
printf("%lld\n", vec.front());
}
return 0;
}
D题
还是暴力。
相当于判断,通过代价为零的边,能有多少个连通块,答案为连通块的数目减一。
因为是个完全图,每一个点必然和其他所有点有边,我们把能通过0的边连在一起的点缩成一块。每一个块之间,将必然会使用代价为1的边相连,所以代价为快数-1。
考虑暴力dfs,开vis数组,保证每一个节点只会被访问一次。
每一次dfs考虑没有被vis过的,和不会权值1的边相连的点。
要注意优化,单纯来看时间复杂度是nlogn(用map来搜索了的所有有log)
但是块数如果太多,因为每一次访问都需要遍历所有n个点,将会变成n^2
故再开一个set,访问过的点从set里面删除,每一次脂肪问set里面的点。
这样复杂度就将变成,sigma size(块)*logn
(当然也可以理解成为树就是n个点,n-1条边,所以最后需要块数-1条边)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1e5 + 10;
set<int>s[N],init_s;
int n, m;
int height[N];
int pr[N];
int vis[N];
void init()
{
upd(i, 0, n)
height[i] = 1, pr[i] = i;
upd(i, 1, n)init_s.insert(i);
}
int find_pr(int x)
{
return pr[x] == x ? x : pr[x] = find_pr(pr[x]);
}
void unit(int x, int y)
{
x = find_pr(x);
y = find_pr(y);
if (x == y)return;
if (height[x] < height[y])
swap(x, y);
height[x] += height[y];
pr[y] = x;
}
void dfs(int u)
{
vis[u] = 1;
vector<int>vec;
for (auto p : init_s)
{
if(s[u].find(p)==s[u].end())
vec.push_back(p);
}
for (auto p : vec)init_s.erase(p);
for(auto p:vec) {
if (vis[p])continue;
dfs(p);
unit(u, p);
}
}
int main()
{
n = read(), m = read();
int u, v;
up(i, 0, m)
{
u = read(), v = read();
s[u].insert(v);
s[v].insert(u);
}
init();
int ans = 0;
upd(i, 1, n)
{
if (!vis[i])
{
init_s.erase(i);
dfs(i);
}
}
int nums = 0;
upd(i, 1, n)
{
if (pr[i] == i)nums++;
}
printf("%d\n", nums - 1);
}
橙橙橙