Codeforces Round #706 (Div. 2)(题解)

传送门
在这里插入图片描述在这里插入图片描述题目大意:
给出一组数据n,k;
是都可以找出k个字符串使得
s=a1+a2+…+ak+a(k+1) + res(ak) + …+res(a2)+res(a1)

思路:
对称寻找相同字符,将剩余补充到ak+1

代码:

#include<iostream>
using namespace std;

void solve()
{
  int n,k;
  cin >> n >> k;
  string s;
  cin >> s;
  if(k == 0) {
    cout << "YES" << endl;
    return ;
  }
  if(k*2 >= n){
    cout << "NO" << endl;
    return ;
  }
  bool si = true;
  int len = s.length()-1;
  for(int i = 0;i < k;++i)
  {
    if(s[i] == s[len-i]) continue;
    else {
      si = false;
      break;
    }
  }
  if(si) cout << "YES" << endl;
  else cout << "NO" << endl;
}

int main()
{
  int t;
  cin >> t;
  while(t--){
    solve();
  }
}

题目总结:
字符串处理,思维

传送门
在这里插入图片描述在这里插入图片描述题目大意:
在一串数组中找到第一个没有出现的自然数和数组最大数
然后插入[a+b]/2向上取整,可以插入k次

思路:
如果是一个自然序列,则输出n+k;
否则判断第一个数字是否可以插入
输出n+1或者n

代码

#include<bits/stdc++.h>
using namespace std;

set<int> s;

void solve()
{
    int n,k;
    cin >> n >> k;
    s.clear();
    int m = 0,ma = 0;
    for(int i = 0,x;i < n;++i)
    {
        cin >> x;
        s.insert(x);
        ma = max(x,ma);
    }
    int cnt = 0;
    bool si = true;
    for(set<int>::iterator it = s.begin();it != s.end();++it,++cnt){
        if(*it != cnt) {
            m = cnt;
            si = false;
            break;
        }
    }
    if(k == 0) {
        cout << n << endl;
        return ;
    }
    if(m == 0 && si) {
        cout << n+k << endl;
        return ;
    }
    int l = (m+ma+1)/2;
    if(s.find(l) != s.end()){
        cout << n << endl;
    }
    else cout << n+1 << endl;
}

int main()
{
    int t;
    cin >> t;
    while(t--){
        solve();
    }
}

题目总结:
第一题分成一类情况,
第二题分成两类情况。

传送门
在这里插入图片描述
在这里插入图片描述
题目大意:
给n个x轴和y轴上的点,将所有点x,y 一对一 连接
求所有线长度之和的最小值

思路:
数据大的x,y和依次连接

代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;
long long a[maxn],b[maxn];

void solve() {
	int n;
	cin >> n;
	int c1 = 0,c2 = 0;
	for(int i = 1,x,y;i <= 2*n;++i){
		cin >> x >> y;
		if(x == 0) a[c1++] = fabs(y);
		else b[c2++] = fabs(x);
	}
	sort(a,a+n);
	sort(b,b+n);
	double ans = 0.0;
	for(int i = 0;i < n;++i){
		ans += sqrt(a[i]*a[i] + b[i]*b[i]);
	}
	printf("%.15lf\n",ans);
}

int main() {
	int t;
	cin >> t;
	while(t--) solve();
	return 0;
}

题目总结:
思维+数学

传送门
在这里插入图片描述
在这里插入图片描述
题目大意:
小鱼和zy。
小鱼喜欢向相邻且比它当前数字小的位置移动
zy喜欢向相邻且比它当前数字大的位置移动
小鱼和zy依次选择一个位置
问小鱼选择可以赢的位置个数

思路:
寻找最长下降连续子序列,和最长上升连续子序列
而且他们共用同一个最大值
并且最大长度唯一且取余2为1

代码:

#include<iostream>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
const int maxn = 1e5+5;
int l[maxn],r[maxn];
int a[maxn];

int main()
{
  IO;
  int n;
  cin >> n;
  for(int i = 1;i <= n;++i) cin >> a[i];
  l[1] = 1;
  for(int i = 2;i <= n;++i){
    if(a[i] > a[i-1]) l[i] = l[i-1]+1;
    else l[i] = 1;
  }
  r[n] = 1;
  for(int i = n-1;i > 0;--i){
    if(a[i] > a[i+1]) r[i] = r[i+1] + 1;
    else r[i] = 1;
  }
  int ma = 0;
  for(int i = 1;i <= n;++i) ma = max(ma,max(l[i],r[i]));
  int k = 0;
  for(int i = 1;i <= n;++i) if(l[i] == ma || r[i] == ma) k++;
  int ans = 0;
  for(int i = 1;i <= n;++i) if(l[i] == ma && r[i] == ma) ans++;
  if(k == 1 && ma%2 == 1) cout << ans << endl;
  else cout << 0 << endl;  
}

题目总结:
简化代码需要的变量
尽可能简化空间复杂度和时间复杂度

传送门
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题目大意:
将任意的.转化成X使得所有的X只有一条路径

思路:
将1,4,7列变成X然后将2,3列之间的任意一组点连接起来

代码:

#include<bits/stdc++.h>
using namespace std;

#define IO ios::sync_with_stdio(0),cin.tie(0)
const int maxn = 505;
char a[maxn][maxn];

void solve()
{
    int n,m;
    cin >> n >> m;
    for(int i = 1;i <= n;++i){
            cin >> (a[i]+1);
    }
    if(m == 1) 
    for(int i = 1;i < n;++i)
    {
        if(a[i][m] == 'X' || a[i+1][m] == 'X')
        a[i][m] = a[i+1][m] = 'X';
    }
    for(int i = 1;i <= m;i+=3)
    {
        for(int j = 1;j <= n;++j)
        {
            a[j][i] = 'X';
        }
        if(i+2 > m) break;
        int r = 1;
        for(int j = 1;j <= n;++j)
        {
            if(a[j][i+1] == 'X' || a[j][i+2] == 'X') r = j;
        }
        a[r][i+1] = a[r][i+2] = 'X';
    }
    if(m%3 == 0){
        for(int i = 1;i <= n;++i)
        {
            if(a[i][m] == 'X') a[i][m-1] = 'X';
        }
    }
    for(int i = 1;i <= n;++i){
        for(int j = 1;j <= m;++j){
            cout << a[i][j];
        }
        cout << endl;
    }
    return ;
}


int main()
{
    IO;
    int t;
    cin >> t;
    while(t--) solve();
    return 0;
}

题目总结:
思维+暴力

传送门
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述层序遍历

#include<bits/stdc++.h>
using namespace std;

#define LL long long
const int maxn = 405;
const int mod = 998244353;
vector<int> g[maxn];
LL dis[maxn][maxn],ans[maxn][maxn],vis[maxn];
int n;

void bfs(int begin)
{
    for(int i = 1;i <= n;++i) dis[begin][i] = 1e18;
    queue<int> q;
    q.push(begin);
    dis[begin][begin] = 0;
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        for(int i = 0;i < g[x].size();++i)
        {
            int t = g[x][i];
            if(dis[begin][t] > dis[begin][x]+1){
                dis[begin][t] = dis[begin][x] + 1; 
                q.push(t);
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int m;
    cin >> n >> m;
    for(int i = 1;i <= m;++i){
        int x,y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }   
    for(int i = 1;i <= n;++i) bfs(i);
    //cout << "QAQ1" << endl;
    for(int i = 1;i <= n;++i){
        //cout << "QAQ2" << endl;
        for(int j = 1;j <= i;++j){
            //cout << "QAQ3" << endl;
            memset(vis,0,sizeof(vis));
            int sx = i,tx = j;
            while(sx != tx){
                //cout << "QAQ4" << endl;
                vis[sx] = 1;
                for(int k = 0;k < g[sx].size();++k){
                    int t = g[sx][k];
                    if(dis[i][sx]+1 == dis[i][t]
                    && dis[j][sx] == dis[j][t]+1 ){
                        sx = t;
                        break;
                    }
                }
            }
            vis[tx] = 1;
            ans[i][j] = 1;
            for(int k = 1;k <= n;++k){
                if(!vis[k]){
                    int cnt = 0;
                    for(int l = 0;l < g[k].size();++l){
                        int t = g[k][l];
                        if(dis[i][k] == dis[i][t]+1
                            && dis[j][k] == dis[j][t]+1)
                            cnt++;
                    }
                    vis[k] = 1;
                    ans[i][j] = ans[i][j]*cnt%mod;
                }
            }
            ans[j][i] = ans[i][j];
        }
    }
    for(int i = 1;i <= n;++i){
        for(int j = 1;j <= n;++j){
            cout << ans[i][j] << " ";
        }
        cout << endl;
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值