AtCoder Beginner Contest 276 CDEF题解

C
题意:求这个排列的上一个排列。

直接用STL自带的求排列即可。

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 x first
#define y second
const int N=2e5+10;
const double eps=1e-4;
typedef pair<int,int> pii;

int a[N];
void work()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	prev_permutation(a+1,a+1+n);
	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	cout<<endl;
}  
signed main()
{
	int t;
	//cin>>t;
	t=1;
	while(t--)
	{
		work();
	}
	return 0;
}

D
题意:给定数组A,每次可选则下列两种操作:
1.把 a i a_i ai 变为 a i a_i ai/2 .( a i a_i ai要为2的倍数)
2.把 a i a_i ai 变为 a i a_i ai/3 .( a i a_i ai要为3的倍数)

问能否通过这些操作,把A中元素变成相等的。
若可以,求出总的最小操作次数,若不可以,输出-1。

思路:我是贪心的做的,也就是把最小的一个数拿出来,分解到直到不能被2或3整除。然后看是否其他数能否最后也分解成这个数。
若可以分解为这个数,答案就是总的次数-共有的因子的数量,否则,答案为-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 x first
#define y second
const int N=2e5+10;
const double eps=1e-4;
typedef pair<int,int> pii;

int a[N];
int x[N],y[N];
void work()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+1+n);
	int m;
	while(a[1]){
		if(a[1]%2==0){
			a[1]/=2; x[1]++;
		}
		else if(a[1]%3==0){
			a[1]/=3; y[1]++;
		}
		else {
			m=a[1]; break;
		}
	}
	for(int i=2;i<=n;i++){
		while(a[i]!=m)
		{
			if(a[i]%2==0){
				a[i]/=2; x[i]++;
			}
			else if(a[i]%3==0){
				a[i]/=3; y[i]++;
			}
			else {
				cout<<-1<<endl;
				return ;
			}
		}
	}
	int ans=0;
	int cnt1,cnt2; 
	cnt1=1e9,cnt2=1e9;
	for(int i=1;i<=n;i++){
		cnt1=min(cnt1,x[i]); 
		cnt2=min(cnt2,y[i]);
	}
	for(int i=1;i<=n;i++){
		ans+=x[i]-cnt1;
		ans+=y[i]-cnt2;
	}
	cout<<ans<<endl;
}  
signed main()
{
	int t;
	//cin>>t;
	t=1;
	while(t--)
	{
		work();
	}
	
	return 0;
}

E
题意:有n*m的网格,给定起点和障碍物的位置,起点只有一个,问是否存在一条路,从起点出发,最后又回到起点,且路径长>=4.

直接进行dfs,如果能够找到一条路径就直接返回即可,同时为了防止每个点被遍历多次,要记录被遍历过的点。同时题目只告诉了n*m的范围,但没告诉n和m的范围,因此需将二维坐标映射成一维。

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=4e6+10;
const double eps=1e-4;
typedef pair<int,int> pii;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};

int n,m;
char mp[N];
bool st[N];
int sx,sy;
int get(int i,int j)
{
	return (i-1)*m+j;
}
bool dfs(int x,int y,int cnt)
{
	for(int i=0;i<4;i++){
		int a=dx[i]+x,b=dy[i]+y;
		if(a==sx&&b==sy&&cnt>=4) return 1;
		if(a<1||a>n||b<1||b>m||st[get(a,b)]||mp[get(a,b)]=='#') continue;
		st[get(a,b)]=1;
		
		if(dfs(a,b,cnt+1)) return 1;
	}
	return 0;
}
void work()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char s;
			cin>>s;
			if(s=='S') {
				sx=i,sy=j;
			}
			mp[get(i,j)]=s;
		}
	}
	st[get(sx,sy)]=1;
	if(dfs(sx,sy,1)) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	
}  
signed main()
{
	ios;
	int t;
	//cin>>t;
	t=1;
	while(t--)
	{
		work();
	}
	
	return 0;
}

F
题意:一共有n个球,值为 a i a_i ai ,按顺序每次将一个球加入到箱子里,然后从箱子里有放回的拿出两个球,求max( a x a_x ax a y a_y ay)的期望值。

思路:很明显暴力求解的话必然会超时,考虑优化,可以发现假设当前箱子有了3,6,5,2,1这几个求,要把4加进来,那么其对答案的贡献是什么呢? 应该是4本身, 加上里面 ≤ \leq 4的球的个数x*4,再加上 大于4的所有球的值的和。 可以想到用树状数组来动态的维护两个值,一个是个数,一个是类似于前缀和的形式。
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=3e5+10,mod=998244353;
const double eps=1e-4;
typedef pair<int,int> pii;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
int a[N];
int tr[N],tr1[N];
int qmi(int a,int k)
{
	int ans=1;
	while(k)
	{
		if(k&1) ans=ans*a%mod;
		a=a*a%mod;
		k>>=1;
	}
	return ans;
}
int lowbit(int x)
{
	return x&-x;
}
void add(int x,int c)
{
	for(int i=x;i<N;i+=lowbit(i)) tr[i]+=c;
}
int sum(int x)
{
	int ans=0;
	for(int i=x;i;i-=lowbit(i)) ans+=tr[i];
	return ans;
}
void add1(int x,int c)
{
	for(int i=x;i<N;i+=lowbit(i)) tr1[i]+=c;
}
int sum1(int x)
{
	int ans=0;
	for(int i=x;i;i-=lowbit(i)) ans+=tr1[i];
	return ans;
}
void work()
{
	int n;
	cin>>n;
	int ans=0,tot=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		tot+=a[i];
		
		add(a[i],1); add1(a[i],a[i]);
		int x=sum(a[i]),y=tot-sum1(a[i]);
		
		//cout<<x<<"####"<<y<<endl;
		
		ans=(ans+(2*(x-1)*a[i]%mod+2*y+a[i]))%mod;
		int p=i*i%mod;
		cout<<ans*qmi(p,mod-2)%mod<<endl;
	}
}  
signed main()
{
	ios;
	int t;
	//cin>>t;
	t=1;
	while(t--)
	{
		work();
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值