Codeforces Round #810 (Div. 2) A,B,C

A

题目大意:

  • 给定一个n,找出1~n的所有排列中,最小的一种排列
  • 值被定义为, ∑ i = 1 n ( a i % i = = 0 ) \sum_{i=1}^{n}(a_{i}\%i==0) i=1n(ai%i==0)

解法:

  1. 首先可以发现对于 i = 1 i=1 i=1的情况,不管 a 1 a_{1} a1取什么值都会满足 1 ∣ a 1 1 \mid a_{1} 1a1
  2. 一种构造方法为,第一个位置取最后一个元素,其他位置都取 i − 1 i-1 i1这个元素,那么值一定为1
#include <iostream>

using namespace std;

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        int n;
        cin >> n;
        cout << n << " ";
        for(int i = 1;i < n;i ++) cout << i << " ";
        cout << endl;
    }
}

B

题目大意:

  • 有n个人,现在需要从n个人中邀请一些人参加聚会
  • n个人中,有m对朋友,如果一对朋友中的2个人都被邀请了,那么它们平分一块蛋糕,所需蛋糕数量为被邀请人中的朋友对数量
  • n个人编号为1~n,如果第 i i i个没有被邀请,那么聚会就会产生 a i a_{i} ai的不快乐值
  • 限制蛋糕的数量只能为偶数,问聚会的最小不快乐值是多少

解法:

  1. 首先假设邀请了所有人,怎么计算目前的需要的蛋糕数量
  2. 可知,这时候需要的蛋糕数量为m,因为n个人中有m对朋友
  3. 如果m为偶数,那么所有人都可以邀请
  4. 如果m为奇数,那么就需要去掉几个人使得朋友对为偶数
  5. 把朋友关系想象成一张图,那么可以发现这张图的数量其实就是朋友对的数量,那么去掉一些人使得朋友对数量为偶数,其实也就是在图中去掉几个点使得图中边的数量为偶数
  6. 那么就可以记录所有点对应的度数
  7. 那么就考虑去除那些点会让边数为偶数
  8. 首先如果一个点的度数为奇数,那么这个点去掉可以让边数为偶数
  9. 然后就是2个相邻点,如果度数都为偶数的话,去掉之后,边数也为偶数,所以答案,就是取这2种情况的最小值
#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int d[N], a[N];

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        int n, m;
        cin >> n >> m;
        for(int i = 1;i <= n;i ++)
        {
            cin >> a[i];
            d[i] = 0;
        }
        int temp = 0x3f3f3f3f;
        for(int i = 1;i <= m;i ++)
        {
            int u, v;
            cin >> u >> v;
            d[u] += 1, d[v] += 1;
            temp = min(temp, a[u] + a[v]);
        }
        if(m & 1)
        {
            int res = 0x3f3f3f3f;
            for(int i = 1;i <= n;i ++) if(d[i] & 1) res = min(res, a[i]);
            cout << min(res, temp) << endl;
        }
        else cout << 0 << endl;
    }
    return 0;
}

C

题目大意:

  • 给定一个 n × m n \times m n×m的表格,以及 k k k种颜色,每种颜色最多可以涂 a i a_{i} ai个格子
  • 问存不存在一种方案,可以使用这些颜色涂满所有格子,满足对于 ( i , j ) (i, j) (i,j)这个格子,它的相邻格子中至少有3个格子颜色和它一样,这里的相邻比较特殊,指的是如果处于边界,那么相邻的格子出了边界就是对立边界中相应的格子

解法:

  1. 通过构造几组数据可知,如果一个颜色要被涂上格子,那么这个颜色一定会占用表格的 x x x行或者 x x x ( 2 ≤ x ≤ n 或者 m ) (2\le x \le n或者m) (2xn或者m)
  2. 那么对于每一种颜色,如果这种颜色可以涂满超过2行或者2列,就记录可以涂的数量,如果最后数量不够 n ∗ m n * m nm个,就不行
  3. 如果数量满足,对于按行的以及按列的再分2种情况,如果按列涂,那么如果有偶数列,就可以实现;如果有奇数列,就还需判断是否存在一个颜色可以涂3列,如果可以就能满足条件,另一种情况类似。
#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int a[N];
typedef long long ll;

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        ll n,m,k;
        cin >> n >> m >> k;
        for(int i = 1;i <= k;i ++) cin >> a[i];
        ll res1 = 0, res2 = 0;
        for(int i = 1;i <= k;i ++) 
        { 
            if(a[i] >= 2 * n)
                res1 += (a[i] - a[i] % n);
            if(a[i] >= 2 * m)
                res2 += (a[i] - a[i] % m);
        }
        // cout << res1 << " " << res2  << endl;
        if((res1 < n * m) && (res2 < n * m)) puts("No");
        else
        {
            int flag = 0;
            if(res1 >= n * m)
            {
                if(m % 2 == 0) flag = 1;
                else
                {
                    for(int i = 1;i <= k;i ++)
                        if(a[i] >= 3 * n) flag = 1;
                }
            }
            if(res2 >= n * m)
            {
                if(n % 2 == 0) flag = 1;
                else
                {
                    for(int i = 1;i <= k;i ++)
                        if(a[i] >= 3 * m) flag = 1;
                }
            }
            if(flag) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值