Educational Codeforces Round 89 (Rated for Div. 2)A-B-C-D

Educational Codeforces Round 89 (Rated for Div. 2) 传送门

A. Shovels and Swords
题意:你可以制作两种工具,分别是铲子和剑,制作一把铲子需要2个木棍和1个钻石,制作一把剑需要1个木棍和2个钻石,每个工具可以获得1个翡翠,给你a个木棍和b个钻石,求出最多可获得多少翡翠

题解:在群友大佬们都卡了下这道题,所以还是详细写写思维
先保证a<b,因为木棍和钻石的钟类交换大小并无影响
①a<=2b,选出a与b的差值过大、a=0的情况,此时能获得的翡翠ans=a
②假设a为木棍,b为钻石,可以制作x把铲子,y把剑,故ans=x+y,消耗的木棍为a≥2
x+y,消耗的钻石为b≥x+2y,两式相加可得a+b≥3x+3*y,即ans=x+y≤(a+b)/3

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
      	ll a,b,ans=0;
      	cin>>a>>b;
      	if(a>b)swap(a,b);
      	 if(b>=2*a)ans=a;
		else {
			ans=(a+b)/3;
		}
		cout<<ans<<endl;
    }
    return 0;
}

B. Shuffle
题意:长度为n,从1-n的数组a,只有a[x]=1,其他的a[i]都为0,可以进行m次操作,每次可以在区间[l,r]中交换任意两数,求出可能出现1的区间长度大小k

题解:起始区间是[a,b]且a=b=x,有区间交集时,就可以贪心向左或者向右扩大区间长度,k=b-a+1

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define endl  '\n'
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
      	int n,x,m;
      	cin>>n>>x>>m;
      	int l=x,r=x,a=0,b=0;
      	for(int i=0;i<m;i++)
      	{
      		cin>>a>>b;
			if(!(a>r)&&!(b<l)){        //判断区间是否有交集 
				l=min(l,a);r=max(r,b);
			}	
		}
      	cout<<r-l+1<<endl;
    }
    return 0;
}

C. Palindromic Paths
题意:一个nm的矩阵,只有0和1;从(1,1)到(n,m)且只能往右和往下,按顺序记录条路径经过的0和1,现在你可以改变nm原矩阵内任意位置的01,需要保证任意路径记录下的01串都是回文串,求需要改变01的最少次数

题解:最直接就是bfs暴力模拟,由于本人太菜,只能瞎搞方法
步数遍历
可以发现沿主对角线,左上到(1,1)和右下到(n,m)的最短距离相同,
只需要统计这样对称的两点的0和1个数分别的和,找出出现次数最少的,即是每次需要改变01次数的最小值。

在这里插入图片描述

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define endl  '\n'
using namespace std;
int a[70][2];
int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;cin>>t;
    while(t--)
    {
    	//memset(a,0,sizeof(a));
    	int n,m,x;cin>>n>>m;
    	for(int i=1;i<=n;i++)
		 	for(int j=1;j<=m;j++)
			a[i+j][0]=0,a[i+j][1]=0;
		 for(int i=1;i<=n;i++)
		 {
		 	for(int j=1;j<=m;j++)
		 	{
		 		cin>>x;
		 		a[i+j-1][x]++;
			 }
		 }
		 int ans=0,cnt=n+m-1;
		 for(int i=1;i<=cnt/2;i++)
		 {
		 	ans+=min(a[i][0]+a[cnt-i+1][0],a[i][1]+a[cnt-i+1][1]);
		 }
	   cout<<ans<<endl; 
    }
    return 0;
}

D. Two Divisors
题意:对于a[i],如果能存在d1和d2满足gcd(d1+d2,a[i])=1,即输出两行i位分别输出d1和d2,若不存在就输出-1和-1

题解:预处理先对每个a[i]打表构造一个数组p[i],用于存每个a[i]的最小因数
while循环对a[i]除以p[i],得到a[i]的最小质因数,若最后除得到1则没有最小质因数,若最小质因数+a[i]/最小质因数可以与a[i]互质

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define _for(i,a,b) for(int i = (a);i<(b);i++)
#define endl  '\n'
using namespace std;
const int mod=1e9+7;
const int MAX=1e7+7;
ll p[MAX];
bool vis[MAX];
vector<ll> d1,d2;

int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
     for(int i=2;i<=MAX;i++) {
        if(!vis[i]) {
            for(int j=i;j<=MAX;j+=i){
				p[j] = i;vis[j]=1;
			} 
        }
    }
    int n;cin>>n;
    while(n--)
    {
       ll a;
        cin>>a;
        ll c=a, p1 = p[a];
        while(c%p1==0) c/=p1;
        if(c==1) d1.push_back(-1), d2.push_back(-1);
        else d1.push_back(c), d2.push_back(a/c);	
    }
    for(int i=0;i<d1.size();i++) 
	cout<<d1[i]<<" ";
	cout<<endl;
    for(int i=0;i<d2.size();i++) 
	cout<<d2[i]<<" ";
	cout<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hrd535523596/article/details/106714557