AtCoder Beginner Contest 279 CDE题解

C
题意:给定两个字符数组 S,T,问是否可以通过重排S的列来使S=T。

直接根据题意来模拟判断即可。

code:

#include<bits/stdc++.h>

using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//#define int long long
#define x first
#define y second
const int N=4e5+10;
const double eps=1e-4;
typedef pair<int,int> pii;
string s[N],t[N];
int a[N],b[N];
void work()
{
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>s[i];
	}
	for(int i=0;i<n;i++){
		cin>>t[i];
	}
	
	bool f=0;
	vector<string> a(m),b(m);
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			a[i]+=s[j][i];
			b[i]+=t[j][i];
		}
	}
	sort(a.begin(),a.end()); sort(b.begin(),b.end());
	for(int i=0;i<m;i++){
		if(a[i]!=b[i]){
			f=1; break;
		}
	} 
	if(f) cout<<"No"<<endl;
	else cout<<"Yes"<<endl;
}
signed main()
{
	int t;
	//cin>>t;
	t=1;
	while(t--)
	{
		work();
	}
	return 0;
}

D
题意:判断 A g + x \frac{A}{\sqrt{g+x}} g+x A+B*x 的最小值。

显然由题意可知该函数有最小值,因此三分求最值即可。

code:

#include<bits/stdc++.h>

using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second

const int N=4e5+10;
const double eps=1e-4;
typedef pair<int,int> pii;

double a,b;
double get(int x)
{
	double ans=a/(sqrt(x+1))+x*b;
	return ans;
}
void work()
{
	cin>>a>>b;
	int l=0,r=1e18;
	while(l<r)
	{
		int midl=l+(r-l)/3,midr=r-(r-l)/3;
		if(get(midl)>get(midr)) l=midl+1;
		else r=midr-1;
	}
	double ans;
	if(get(l)<get(r)) ans=get(l);
	else ans=get(r);
	printf("%.10lf\n",ans);
}
signed main()
{
	int t;
	//cin>>t;
	t=1;
	while(t--)
	{
		work();
	}
	return 0;
}

E
题意:有m个数,其值 a i a_i ai 都小于N,给定序列 B N B_N BN, 初始 B i B_i Bi=i,进行m轮操作,每次操作为,选定k=1,2,3…M, 注意第i轮操作时,k!=i。然后交换 B A k B_{A_k} BAk B A k + 1 B_{A_{k+1}} BAk+1,问在每一轮操作后,B数组中1的位置在哪里。

这道题如果暴力的做时间复杂度为 n 2 n^2 n2,即按照题意模拟交换。
考虑转化思路,既然每一轮操作只有一次没有交换,那不妨把这一次也默认交换,然后我们会很容易得到最后1的位置。那考虑若不交换的这一步,若此步含有1,则说明最后实际1的位置就是与1交换的这个数的位置(因为这一步使1和这个数(假设x),互换了位置,因此在后面的交换中,对x交换就是对1交换)最终答案为x的位置,若此步不含1,则说明即使交换这一步对结果也没有影响,所以答案为1的位置。
说的不是很清晰,总之这题的思维转换很妙,值得学习。

code:

#include<bits/stdc++.h>

using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
const int N=2e5+10,mod=998244353;
const double eps=1e-4;
typedef pair<int,int> pii;

int q1[N],q2[N];
int a[N],b[N];
int p[N];

void work()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++) b[i]=i;
	for(int i=1;i<=m;i++){
		int x=a[i],y=a[i]+1;
		q1[i]=b[x],q2[i]=b[y];
		
		swap(b[x],b[y]);
		
	}
	for(int i=1;i<=n;i++) p[b[i]]=i;
	for(int i=1;i<=m;i++){
		if(q1[i]==1) cout<<p[q2[i]]<<endl;
		else if(q2[i]==1) cout<<p[q1[i]]<<endl;
		else cout<<p[1]<<endl;
	}
	
}  

signed main()
{
	ios;
	int t;
	//cin>>t;
	t=1;
	while(t--)
	{
		work();
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值