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