Codeforces Round #597 (Div. 2)题解A~D

Good ol’ Numbers Coloring

在这里插入图片描述
在这里插入图片描述
题目大意就是说:给定两个数字a b让你给不同的自然的数按照给定的规律染成黑色或白色
规律是 假如 i = 0 染成白色
假如 i >= a && i - a是白色那么i也是白色
假如 i >= b && i - b是白色那么i也是白色

现在问你是否有无限个数字被染成黑色?

对于黑色有无限个那么白色是有限个
一个数如果是a 或 b的倍数那么它一定被染成白色
表达式就i可以写成ax + by = i;
那么i一定是gcd(a,b)|i 要满足有无限个白色那么gcd(a,.b) == 1;

#include <iostream>
#include <algorithm>

using namespace std;
int gcd(int a,int b)
{
    return b ? gcd(b,a % b) : a;
}
int main()
{
    int T;
    int n, m;
    cin >> T;
    while(T--)
    {
        cin >> n >> m;
        if(m < n) swap(n,m);
        if(gcd(n,m) != 1) puts("Infinite");
        else puts("Finite");
    }
    return 0;
}

Restricted RPS

在这里插入图片描述
一道简单的模拟题
一开始把向上取整看错了wa了两发qwq
还有floor函数和ceil函数要用double类型

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;
const int N = 310;

char f[N];
char Bob[N];
int a, b, c;

int main()
{
    double T, n;
    cin >> T;
    while(T --)
    {
       cin >> n;
       for(int  i = 0; i <= n + n; ++ i) f[i] = '#';
       cin >> a >> b >> c;
       cin >> Bob;
       int ans = 0;
       for(int i = 0; i < n; ++ i)
       {
           if(Bob[i] == 'R' && b != 0) 
           {
               ans ++;
               f[i] = 'P';
               b --;
           }
           else if(Bob[i] == 'P' && c != 0)
           {
               ans ++;
               f[i] = 'S'; 
               c --;
           }
           else if(Bob[i] == 'S' && a != 0)
           {
               ans ++;
               f[i] = 'R'; 
               a --;
           }
       }
      double t = (double) n / 2;
       if(ans >= (ceil(t)))
       {
           cout << "YES" << endl;
           for(int i = 0; i < n; ++ i)
           {
               if(f[i] == '#')
               {
                   if(a != 0)
                   {
                       f[i] = 'R';
                       a --;
                   }
                   else if(b != 0)
                   {
                       f[i] = 'P';
                       b --;
                   }
                   else if(c != 0)
                   {
                       f[i] = 'S';
                       c--;
                   }
               }
               cout << f[i];
           }
           cout << endl;
       }
       else cout << "NO" << endl;
       
    }
    return 0;
}

在这里插入图片描述
在这里插入图片描述

Constanze’s Machine

一道简单的dp
就是给你一个字符串这个字符串中uu把w替换了。 nn把m替换了。现在该你一个字符串求它的原串的种类有多少个。假如说出现了m 和 w 的就输出0

下面我们来看一下我们只要讨论uu和nn的个数就可以了。
nn => nn 和 m 2 种
nnn => nnn 和 nm 和 mn 3种
很明显就是再前一个串的基础上加个n
如果出现了连续连续两个nn再将其合并·
nnnn => nnnn 和 mnn 和 nmn 和 mm 和 mnn 5种 可以现前3个就是nnn的情况加上一个n 。后面是 nn 的情况加上m 所以递推公式就是f[i] = f[i - 1] + f[i - 2];

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long LL;
const int N = 1e5 +10, mod = 1e9 + 7;

char f[N];
LL fei[N];
int main()
{
   cin >> f + 1;
   int len = strlen(f + 1);
   fei[1] = 1, fei[2] = 2;
   for(int i = 3; i <= N; ++ i)
       fei[i] = (fei[i - 1] % mod + fei[i - 2] % mod) % mod;
   LL ans = 1;
   
   for(int i = 1; i <= len; ++ i)
   {
       int j = i;
       if(f[j] == 'u')
       {
           while(f[j] == 'u') j ++;
           ans *= fei[j - i];
           ans %= mod;
           i = j - 1;
       }
       else if(f[j] == 'n')
       {
           while(f[j] == 'n') j++;
           ans *= fei[j - i];
           ans %= mod;
           i = j - 1;
       }else if(f[j] == 'm' || f[j] == 'w')
       {
           cout << "0" << endl;
           return 0;
       }
   }
   cout << (ans % mod + mod) % mod << endl;
   
   return 0;
}

吐槽一下qwq ans %= mod 打的时候漏了等号qwq

Shichikuji and Power Grid

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
就是一个最小生成树的板子题
题意是在一个二维平面上有一堆城市每个城市一开始是没有电的现在我们决定在某些城市建立发电站,一个城市可以不用建发电站只要拉电线去一个有电的城市就可以了
下面给出n个城市的坐标和每个城市建电站的花费,还有给出每个城市拉电线的费用
等于两个城市之间的曼哈顿距离乘以(ki + kj);

看一下城市的个数2000建立一个完全图只要2e6条边每条边的边权就是拉电线的费用那么发电站是点权怎么转化为边权呢
建立一个超级原点每个点都接上去边权就是建发电站的费用这样就变成了最小生成树的裸题了
我们还要记录发电站的位置和边

克鲁斯卡尔算法直接套板子

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 4e6 +2000, mod = 1e9 + 7;
struct node{
    LL to, from, v;
    bool operator < (const node & w) const 
    {
        return v < w.v;
    }
}e[N];

int n;
PII p[N];
int k[N], c[N], fa[N];
int k1 = 0, p1 = 0;
//..................................................
inline int find(int x)
{
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

inline void Union(int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if(fx != fy) fa[fx] = fy;
    
    return;
}

int main()
{
    LL ans = 0;
    scanf("%d",&n);
    for(int i = 1; i <= n; ++ i)
         scanf("%d%d",&p[i].x,&p[i].y);
    for(int i = 1; i <= n; ++ i)
         scanf("%d",&c[i]);
    for(int i = 1; i <= n; ++ i)
         scanf("%d",&k[i]);
//..................................................
    int cnt = 0;
    for(int i = 1; i <= n; i ++)
       e[cnt ++] = {0,i,c[i]};
       
     for(int i = 1; i <= n; ++ i)
       for(int j = i + 1; j <= n; ++ j)
     e[cnt ++] = {i,j,(abs(p[i].x - p[j].x) + abs(p[i].y - p[j].y)) * 1ll * (k[i] + k[j])};
      
      sort(e,e + cnt);
//.................................................

      for(int i = 0; i <= n; ++ i) fa[i] = i;
      
      for(int i = 0; i < cnt; ++ i)
      {
          if(p1 + k1 == n) break;
          if(find(e[i].to) != find(e[i].from))
          {
              Union(e[i].to,e[i].from);
              if(!e[i].to) k[k1 ++] = e[i].from;
              else if(!e[i].from) k[k1 ++] = e[i].to;
              else p[p1 ++] = {e[i].to,e[i].from};
              ans += e[i].v;
          }
      }
      
 //...................................................
      
      cout << ans << endl;
      cout << k1 << endl;
      sort(k,k + k1);
      for(int i = 0; i < k1; ++ i)
        i == k1 - 1 ? cout << k[i] << endl : cout << k[i] <<" ";
      cout << p1 << endl;
       for(int i = 0; i < p1; ++ i)
         cout << p[i].x <<" "<< p[i].y << endl;
         
         return 0;
       
}

还有就是求拉电线的时候忘记longlongwa了两发qwq

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值