Codeforces Round #777 (Div. 2) 简训

导语

日常训练,官方题解写的好麻烦…

涉及的知识点

思维,模拟,数论,分类

链接:Codeforces Round #777 (Div. 2)

题目

A Madoka and Math Dad

题目大意:给出一个正整数n,构造出一个正整数x,x每一位不为0,相邻两位不相同,并且x尽量大

思路:与其让位上的数大,不如让位数更多,直接拆成1和2即可

代码

#include <bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e5+5;
int n,t;
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>n;
        int ans=n/3,res=n%3;//拆成多个1+2
        if(res==1)//如果剩下的是1,那么12循环
            while(ans--)cout <<12;
        else//否则21循环
            while(ans--)cout <<21;
        if(res)cout <<res;
        cout <<endl;
    }
    return 0;
}

B Madoka and the Elegant Gift

题目大意:略

思路:直接判断每个2×2的矩阵里是不是恰好有3个黑,如果有则一定不行

代码

#include <bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e5+5;
int n,t,m,Next[4][2]= {0,1,0,-1,1,0,-1,0};
char maze[121][121];
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>n>>m;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                cin >>maze[i][j];
        bool flag=0;
        for(int i=1; i<=n-1; i++)
            for(int j=1; j<=m-1; j++) {
                int ans=0;
                for(int k=i; k<=i+1; k++)
                    for(int p=j; p<=j+1; p++)
                        if(maze[k][p]=='1')
                            ans++;
                if(ans==3)flag=1;
            }
        flag?cout <<"NO\n":cout <<"YES\n";
    }
    return 0;
}

C Madoka and Childish Pranks

题目大意:略

思路:贪心的想,每次拿上白下黑或者左白右黑的2×2即可,一开始想着从上向下涂,但是不行,因为这样最后一个块就无法修正了,因此从最后一行最后一个开始向前涂,因为前一个是可以通过一个单独的白修正的

代码

#include <bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e5+5;
int n,t,m,x1[maxn],y1[maxn],x2[maxn],y2[maxn];
char maze[121][121],op[121][121];
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>n>>m;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++) {
                cin >>maze[i][j];
                op[i][j]='0';
            }
        if(maze[1][1]=='1') {//只有左上角为黑的时候才无解
            cout <<-1<<endl;
            continue;
        }
        int ans=0;
        for(int i=n; i>=1; i--)//从最后一行开始填
            for(int j=m; j>=1; j--) {
                if(op[i][j]==maze[i][j])continue;//如果一样就跳过
                if(op[i][j]=='0'&&maze[i][j]=='1') {//如果要白变黑
                    if(j==1) {//第一个,只能向上一个拓展
                        op[i][j]='1';
                        op[i-1][j]='0';
                        x1[++ans]=i-1;
                        y1[ans]=j;
                        x2[ans]=i;
                        y2[ans]=j;
                    } else {//否则向左拓展
                        op[i][j]='1';
                        op[i][j-1]='0';
                        x1[++ans]=i;
                        y1[ans]=j-1;
                        x2[ans]=i;
                        y2[ans]=j;
                    }
                } else if(op[i][j]=='1'&&maze[i][j]=='0') {//黑变白直接赋值即可
                    op[i][j]='0';
                    x1[++ans]=i;
                    y1[ans]=j;
                    x2[ans]=i;
                    y2[ans]=j;
                }
            }
        cout <<ans<<endl;
        for(int i=1; i<=ans; i++)
            cout <<x1[i]<<" "<<y1[i]<<" "<<x2[i]<<" "<<y2[i]<<endl;
    }
    return 0;
}

D Madoka and the Best School in Russia

题目大意:给出相关定义:如果一个数是d的倍数,那么这个数被认为是好数,如果一个数是好数并且不能被表示为两个好数的乘积,那么这个数就是美数,现在给出一个关于d的好数x,判断它是否至少有两种分解方式表示为多个美数的乘积(不同的定义为使用的数字集合不同)

思路:分多种情况讨论,假设 x = b × d a , b % d ≠ 0 x=b×d^a,b\%d≠0 x=b×da,b%d=0

  1. a = 1 a=1 a=1,此时 x x x只能分成 b × d b×d b×d,或者把 b b b拆分,显然不管是 b b b还是拆分后的 b b b都不是好数,则输出 N O NO NO
  2. b b b为合数且 a > 1 a\gt 1 a>1,显然可以将 b b b拆成几个数之积,每个数分配一个 d d d,并且有多种拆分和分配方式,输出 Y E S YES YES
  3. d d d为质数( b b b为质数),显然没办法拆,和第一种情况一样,输出 N O NO NO
  4. d d d为合数且不为质数的幂数( b b b为质数),如果 a = 2 a=2 a=2,那么还是只能拆成 b × d b×d b×d d d d,输出 N O NO NO,否则若 a > 2 a>2 a>2,那么一定可以将一个 d d d分解成 p × q ( g c d ( p , q ) = 1 ) p×q(gcd(p,q)=1) p×qgcd(p,q)=1,将 d d d b , q , p b,q,p b,q,p等进行配对与组合即可,一定有多种方式(例如 a = 3 a=3 a=3,可以得到 q × b × d q×b×d q×b×d p × d p×d p×d)输出 Y E S YES YES
  5. d d d为合数且为质数的幂数( b b b为质数),假设 d = p k d=p^k d=pk,情况就变得复杂起来,只有 d = p 2 , x = p 7 d=p^2,x=p^7 d=p2,x=p7时是 N O NO NO,具体解释如下,如果 a > 2 , k > 1 a>2,k>1 a>2,k>1,那么可以将 d a = p a k d^a=p^{ak} da=pak分成 p 2 k − 1 , p k + 1 , p k , … p^{2k-1},p^{k+1},p^k,\dots p2k1,pk+1,pk,,即 p k − 1 d , p d , d , … p^{k-1}d,pd,d,\dots pk1d,pd,d,,如果 k > 2 ( a > 2 ) k>2(a>2) k>2(a>2),即使 b = p b=p b=p,则原式= p a k + 1 p^{ak+1} pak+1仍然可以分成至少两种: p k , p k − 1 p k , b p p k , … p^k,p^{k-1}p^k,bpp^k,\dots pk,pk1pk,bppk, p k , p k − 2 p k , b p 2 p k , … p^k,p^{k-2}p^k,bp^2p^k,\dots pk,pk2pk,bp2pk,,但是,当 k = 2 , a = 3 , b = p k=2,a=3,b=p k=2,a=3,b=p时,无论如何都无法拆分出两种方案,输出 N O NO NO,其余为 Y E S YES YES

那么第5,6其实可以合并得到:d为合且a=2不行,k=2,a=3,b=p不行其余都行

代码

#include <bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=5e5+5;
int t,x,d;
int prime(int x) {
    if(x==2)return -1;
    if(x%2==0)return 2;
    for(int i=3; i<=x/i; i+=2)
        if(x%i==0)return i;
    return -1;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >>t;
    while(t--) {
        cin >>x>>d;
        int cnt=0;
        while(x%d==0) {
            ++cnt;//获得a
            x/=d;
        }
        if(cnt==1) {//a=1
            cout <<"NO\n";
            continue;
        }
        if(prime(x)!=-1) {//b为合数且a>1
            cout <<"YES\n";
            continue;
        }
        if(prime(d)!=-1&&d==prime(d)*prime(d))//d为合数且k=2
            if(x==prime(d)&&cnt==3) {//b=p,a=3
                cout <<"NO\n";
                continue;
            }
        if(cnt>2&&prime(d)!=-1) {//a>2且d为合数
            cout <<"YES\n";
            continue ;
        }
        cout <<"NO\n";//d为质数
    }
    return 0;
}

参考文献

  1. Tutorial
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值