Codeforces Round #818 (Div. 2)

Codeforces Round #818 (Div. 2)

感觉很抽象的一场

A.Madoka and Strange Thoughts

题意:

找到 1 ≤ a , b ≤ n 1\leq a,b\leq n 1a,bn满足 l c m ( a , b ) g c d ( a , b ) ≤ 3 ① \frac {lcm(a,b)}{gcd(a,b)}\leq 3① gcd(a,b)lcm(a,b)3①

Proof1:

A s   w e   k o w n ,   l c m ( a , b ) = a × b g c d ( a , b ) , s o  ① = a × b g c d ( a , b ) 2 ≤ 3 As\ we\ kown,\ lcm(a,b)=\frac{a\times b}{gcd(a,b)},so\ ①=\frac{a\times b}{gcd(a,b)^2}\le 3 As we kown, lcm(a,b)=gcd(a,b)a×b,so =gcd(a,b)2a×b3

我们令d=gcd(a,b),那么 ① = a d × b d ≤ 3 ①=\frac{a}{d}\times \frac{b}{d}\leq3 =da×db3 a d a n d b d \frac{a}{d}and\frac{b}{d} daanddb都是整数,所以他们只有这几种可能:

a/d=1,b/d=1

a/d=1,b/d=2 & a/d=2,b/d=1

a/d=1,b/d=3 & a/d=3, b/d=1

即:

a:b=1,a:b=2,a:b=1:2,a:b=3,a:b=1:3

所以:

ans = n / 1 + (n / 2 + n / 3) * 2

Proof2:

lcm(a,b)=gcd(a,b)

lcm(a,b)=2gcd(a,b)

lcm(a,b)=3gcd(a,b)

Obviously,① → a = b \rightarrow a=b a=b

因为2 and 3 are both primes,所以他们加入不到 g c d gcd gcd中,所以在接下来两个式子中, l c m lcm lcm的变化就是全部的变化,所以变化就是a or b变为2 or 3倍。

#include <bits/stdc++.h>
#define int long long 
#define endl '\n'

using namespace std;

const int N = 1e5 + 10;

int n;

void solve()
{
    cin >> n;
    int res = n + 2 * (n / 2 + n / 3);
    cout << res << endl;
}
signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int T; cin >> T;
    while(T--) solve();
    return 0;
}

B.Madoka and Underground Competitions

在图上构造(秃。。。看到这种就头疼

题意:在一个 n × n n\times n n×n的矩阵上放 .   o r   X .\ or\ X . or X,满足每 1 × k , k × 1 1\times k,k\times1 1×k,k×1的子矩阵中至少有一个 X X X,并且 ( r , c ) (r,c) (r,c)位置必须是 X X X,保证 n n n k k k的倍数,也就是说我们可以根据限制条件构造若干个重复的 k k k单位长度的矩阵。

具体实现的话,就是根据那个锁定位置的坐标,根据对角线构造,等式为: ( r + c ) % k = = ( i + j ) % k (r+c)\%k==(i+j)\%k (r+c)%k==(i+j)%k

对角线的解释:当 r = i , j = c   o r   r = j , c = i r=i,j=c\ or\ r=j,c=i r=i,j=c or r=j,c=i时无疑是正确的,当不等时,我们让其中一坐标+1,另一个-1,那么在 % k \%k %k的条件下构造出来的图形就是题目要求的图形。

#include <bits/stdc++.h>
#define endl '\n'

using namespace std;

const int N = 1e5 + 10;


void solve()
{
    int n, k, r, c;
    cin >> n >> k >> r >> c;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
        if (abs(i + j - r - c) % k == 0) {
            cout << 'X';
        }
        else cout << '.';
        }
        cout << '\n';
    }
}
signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int T; cin >> T;
    while(T--) solve();
    return 0;
}

C.Madoka and Formal Statement

题意:给定两个长度为 n n n的序列,第一行为 a a a,第二行为 b b b,如果 a [ i ] ≤ a [ ( i + 1 ) % n ] a[i]\le a[(i+1)\%n] a[i]a[(i+1)%n],那么让 a [ i ] = a [ i ] + 1 a[i]=a[i]+1 a[i]=a[i]+1,问通过此操作是否可以将第一行序列变为第二行序列。

这道题目标签是贪心,但真没怎么看出来怎么贪QAQ

大概就是:

首先 a [ i ] = b [ i ] a[i]=b[i] a[i]=b[i]是肯定可以的, a [ i ] > b [ i ] a[i]>b[i] a[i]>b[i]是肯定不可以的。

对于剩下情况:因为 a [ i + 1 ] a[i+1] a[i+1]最大能变为 b [ i + 1 ] b[i+1] b[i+1],这时就算可以增加也不会变化了,所以 a [ i ] a[i] a[i]可以达到的最大值是 b [ i + 1 ] + 1 b[i+1]+1 b[i+1]+1,我们只需判断 b [ i ] b[i] b[i]是否小于等于这个最大值,是的话说明通过上述操作我们可以使 a [ i ] → b [ i ] a[i]\rightarrow b[i] a[i]b[i],否则不能,输出 N O NO NO

对于这个贪法是否正确,开始我是持怀疑态度的,但后来感觉确实是这样…

#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

const int N = 2e5 + 10;

int n;
int a[N], b[N];

void solve()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    for (int j = 0; j < n; j++) cin >> b[j];
    for (int i = 0; i < n; i++)
    {   
        if (a[i] == b[i]) continue;
        if (a[i] > b[i] || b[(i + 1) % n] + 1 < b[i]) 
        {
            puts("NO");
            return ;
        }
        
    }    
    puts("YES");
}
signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int T; cin >> T;
    while(T--) solve();
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值