Educational Codeforces Round 89 (Rated for Div. 2)

这次比赛的题目挺好,又是无限wa,这里写下ABCD的题解

传送门

A. Shovels and Swords

主要思路: 找相同的时候,然后 /3 * 2 找最大值

解题思路:
  • 首先我们分情况讨论,最简单的情况就是相同,那么当 a , b 都选出3个的时候,能组成2个,这个是最多的情况,我们还要判断是否是否留了2个,如果留了2个,那么还可以制造一个。
  • 然后我们之间考虑a > b这种情况(换一下即可)。
  • 首先我们看他们之间的差值 x = a - b, 如果 b < x,那么 res = b,这里是因为剩下的a > b的数目,所以我们按照b的数目来制作
  • 然后对于其他情况,我们用 b - x,这里是b 剩下的,这里a,b剩下的数目是相同的,所以我们还是根据第一种情况来计算即可
  • 另外我们最终的目的是为了让他们之间的数目相同,那么我们可以直接写式子
  • a - 2x = b - x , x = a - b,也就是他们的差值
代码:
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N = 100010;

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int a,b;
        scanf("%d%d",&a,&b);
        if (a < b){
            int temp = a;
            a = b;
            b = temp;
        }
        int res = 0;
        if (a == b){
            int x = a / 3;
            res = x * 2;
            if (a % 3 == 2) res ++;
        }
        else{
            int x = a - b;
            if (x >= b) res = b;
            else{
                res =(a - b);
                int num = b-(a-b);
                res += (num/3) * 2;
                if(num%3 == 2) res ++;
            }
        }
        
        printf("%d\n",res);

        
    }
    return 0;
}


B. Shuffle

主要思路: 扩展区间,最终计算区间的长度即可

解题思路:
  • 首先我们要读懂他,他问最终可能有多少个位置的值为1
  • 那么其实就可以转换为可能去扩展当前位为1值的区间
  • 那么我们判断区间是否相交扩大区间即可
代码:
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N = 100010;

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n, x , m;
        scanf("%d%d%d",&n,&x,&m);
        int xxx = x;
        int yyy = x;
        for (int i = 1; i <= m; i++){
            int xx, yy;
            scanf("%d%d",&xx,&yy);
            if (xx <= yyy && yy >= xxx){
                if (xx <= xxx){
                    xxx = xx;
                }
                if (yy >= yyy){
                    yyy = yy;
                }
        }
        }
        printf("%d\n",yyy - xxx + 1);
    }
    return 0;
}


C. Palindromic Paths

主要思路: 首先他的对应步数也就是斜对角线,然后我们记录对应的斜对角线,然后去取0,1的数目,然后res += min(a,b) 即可

解题思路:
  • 首先我们可以找到规律,也就是让相对应的对角线的值全部变成一样的,那么我们就取0或1这两个当中数目较小的进行改变即可。
  • 这个题关键是在输入时就进行预处理,很关键,他的斜对角线就是 i + j -1,然后我们记录他的0,1数目即可。
  • 然后我们计算相应的对角线,正的话就是 i, 反的话就是 n + m - 1, 这里我们从1 循环到 (n + m - 1)/ 2 次。
  • 最终输出结果即可
代码:
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N = 100010;

int a[200][200], ans[200][200];

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
    	memset(a,0,sizeof a);
        int n, m;
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; i++){
        	for (int j = 1; j <= m;j ++){
        		scanf("%d",&ans[i][j]);
        		if (ans[i][j] == 1) a[i + j - 1][1] ++;
        		else a[i + j - 1][0] ++;
        	}
        }
        int res = 0;
        for (int i = 1; i <= (n + m - 1)/2; i++){
        	int x = a[i][0] + a[n + m - i][0];
        	int y = a[i][1] + a[n + m - i][1];
        	res += min(x,y);
        }
        printf("%d\n",res);

    }
    return 0;
}


D. Two Divisors

主要思路: 这题主要是规律题,首先要推出如果 gcd(x,y) == 1 推出 gcd(x + y, x * y ) == 1,然后我们找第一个最小的质因子即可(q^p),让他当做x

解题思路:
  • 首先我们要知道上面推出的公式,然后我们先预处理出1e7以内数的最小质因子
  • 然后我们用最小值因子(q^p)作为x, a[i] / x 作为y,然后我们判断y是否为1即可,如果为1,那么不符合,如果不是1,那么符合。
代码:
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N = 500010;

bool isPrime[12000010]; // 是否为素数
int Prime[12000010]; // 记录素数
int miPrime[12000010];

int a[N];
int b[N][2];

void eulerSieve(int n){
    int num = 1;
    memset(isPrime,true,sizeof isPrime);
    for (int i = 2; i <= n; i++){
        if (isPrime[i]) Prime[num++] = i, miPrime[i] = i;
        for (int j = 1; j < num ; j ++){
            if (i * Prime[j] > n)break;
            isPrime[i*Prime[j]] = false;
            miPrime[i*Prime[j]] = Prime[j];
            if (i % Prime[j] == 0) break;
        }
    }
}

int main(){
    eulerSieve(1e7);
    int n;
    scanf("%d",&n);
    for (int i = 1; i <= n; i++){
        scanf("%d",&a[i]);
    }
    for (int i = 1; i <= n; i++){
        int t = miPrime[a[i]];
        int x = a[i];
        int num = 1;
        while(a[i] % t == 0){
            num *= t;
            a[i] /= t;
        }
        if (x / num == 1){
            b[i][0] = -1;
            b[i][1] = -1;
        }
        else{
            b[i][0] = num;
            b[i][1] = x/num;
        }
    }
    for (int i = 1; i<= n; i++){
        printf("%d ",b[i][0]);
    }
    puts("");
    for (int i  = 1; i <= n; i++){
        printf("%d ",b[i][1]);
    }
    puts("");
    return 0;
}

你可能感兴趣的:(CodeForces,数论,思维)