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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章