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≥2x+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;
}