[cf] Educational Codeforces Round 129 (Rated for Div. 2) A-D

前言

传送门 :
( B > A > C > D B>A>C>D B>A>C>D) 新人友好场 ( E F EF EFQAQ)

A.

题意 :
A l i c e Alice Alice B o b Bob Bob a [ ] a[] a[] b [ ] b[] b[]玩打牌,一人出一个最后不能出的算输,打牌的规则显然是越大越牛,询问两人分别先手的胜负情况

思路 :
这题显然不需要怎么动脑,上来就是一个王炸即可

言简意赅也就是,谁手上有最大的谁就赢,同时有先手赢(思路是显然的不给证明)


这题写慢了,直接 s o r t sort sort或者 ∗ m a x { } *max\{\} max{}会快个几秒钟
code :

int a[N];
int b[N];
int n,m;
void solve(){
	cin>>n;
	int maxna =  0;
	int maxnb = 0 ;
	
	for(int i = 1;i<=n;i++){
		cin>>a[i];
		maxna = max(maxna,a[i]);
	}
	cin>>m;
	
	for(int i=1;i<=m;i++){
		cin>>b[i];
		maxnb = max(maxnb,b[i]);
	}
	
	if(maxna == maxnb){
		cout<<"Alice"<<endl;
		cout<<"Bob"<<endl;
		return;
	}
	
	if(maxna > maxnb){
		cout<<"Alice"<<endl;
		cout<<"Alice"<<endl;
		return;
	}
	cout<<"Bob"<<endl;
	
	cout<<"Bob"<<endl;
	
}

B.

题意 :
给定一个数组 a [ ] a[] a[],和一个询问数组 b [ ] b[] b[],对于每个 b [ i ] b[i] b[i]是将前 a [ b [ i ] ] a[b[i]] a[b[i]]个数放到数组后面,问操作之后首位是多少

思路 :
首先这里的思路其实从 A A A题进行了延申

因为最后答案是求首位是多少,我们贪心的从大局进行考虑,我们发现其实只需要每次交换指向当前首位的指针即可,因为最终都是首位的指针在变

所以我们按操作进行模拟即可

code :

int n,m;
int a[N],b[N];

void solve(){
	cin>>n;
	for(int i = 0 ;i< n; i ++ )cin>>a[i];
	
	cin>>m;
	int u =  0;
	for(int i = 0 ;i<m; i++ ){
		cin>>b[i];
		u = (u+b[i])%n;
	}
	cout<<a[u]<<endl;
	
	
}

C.

题意 :
给定 a [ ] a[] a[], b [ ] b[] b[]询问在有限的操作内是否可以完成排序。

操作定义如下 :
选 中 i . j 选中i.j i.j交换 s w a p ( a [ i ] , a [ j ] ) , s w a p ( b [ i ] , b [ j ] ) swap(a[i],a[j]),swap(b[i],b[j]) swap(a[i],a[j]),swap(b[i],b[j])

思路 :
这题要么就是我做过类似的题,要么就是太简单了

我们可以将 a [ ] a[] a[]看成多个组,然后对 a [ ] a[] a[]进行排序,这样子相同的数会在一起

而相同的 a [ ] a[] a[]就构成了一个组

然后我们在对每个组里面的数进行排序即对 b [ ] b[] b[]进行排序

最后判断一下 b [ ] b[] b[] 是否有序即可

code :

int a[N],b[N];
void solve(){
	vector<pii> ans;
	
	cin>>n;
	mp.clear();
	
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	
	for(int i=1;i<=n;i++){
		for(int j = 1; j < i ;j ++ ){
			if(a[i] < a[j]){
				swap(a[i],a[j]);
				swap(b[i],b[j]);
				ans.pb({i,j});
			}
		}
	}
	
	// for(int i=1;i<=n;i++)
	// cout<<a[i]<<" ";
	// cout<<endl;
// 	
// 	
	for(int i=1;i<=n;){
		int j =  n;
		while(a[j]!=a[i]) j --;
		if(j ==  i){
			i = j+1;
		}
	
		for(int k = i ;k <= j ;k ++){
			for(int t = i ; t < k ; t ++ ){
				if(b[k] < b[t]){
					swap(b[k],b[t]);
					ans.pb({k,t});
				}
			}
		}
		i = j+1;
	}
	
	// for(int i=1;i<=n; i++ )
	// cout<<b[i]<<" ";
	// cout<<endl;
// 	
	for(int i = 2;i<=n;i++){
		if(b[i] < b[i-1]){
			cout<<"-1"<<endl;
			return;
		}
	}
	cout<<ans.size()<<endl;
	for(auto t : ans){
		cout<<t.x<<" "<<t.y<<endl;
		
	}
	

}

int main(){
    int t;cin>>t;while(t--)
    solve();
    return 0 ;
}

D.

题意 :
给定 n , x n,x n,x,询问是最小次数的操作使得 x x x的位数为 n n n

操作定义如下 :
我们可以选中 x x x上的每一位 0 − 9 0-9 09然后令其 x = x ∗ t x=x*t x=xt
如下反复操作

思路 :
因为最小,同时还因为是位数

所以范围在 19 19 19并且是最小,所以考虑 b f s bfs bfs

n ≤ 19 n\le19 n19则说明在 l o n g l o n g long long longlong范围内,因为 1 e 18 1e18 1e18正好 19 19 19位,因此可以在 l l ll ll范围内进行 b f s bfs bfs

就是很简单的 b f s bfs bfs 中间特判一下 0 , 1 0,1 0,1即可

然后就是开 l l ll ll的问题,因为不想开全局 l l ll ll搞得我调了半小时

最后需要特判 1 1 1以及特判 10 , 10 10,10 10,10这种位数上只有 1 , 0 1,0 1,0的情况

code :

// Problem: D. Required Length
// Contest: Codeforces - Educational Codeforces Round 129 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1681/problem/D
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <iostream>
#include <vector>
#include <map>
#include <cstring>
#include <queue>
#include <math.h>
#include <set>
#include <stack>
#include <algorithm>
using namespace std;
#define IOS  ios::sync_with_stdio(false);
#define CIT  cin.tie(0);
#define COT  cout.tie(0);

#define int long long
#define ll long long
#define x first
#define y second
#define pb push_back
#define endl '\n'
#define all(x) (x).begin(),x.end()
#define Fup(i,a,b) for(int i=a;i<=b;i++)
#define Fde(i,a,b) for(int i=a;i>=b;i--)
#define cer(a) cerr<<#a<<'='<<(a)<<" @ line "<<__LINE__<<" "<<endl
typedef priority_queue<int,vector<int>,greater<int>>  Pri_m;
typedef pair<int,int> pii;
typedef vector<int> VI;
map<ll,int> mp;
const int N = 2e5+10,INF = 0x3f3f3f3f;
const double eps = 1e-5;


int n,x;
int get(ll u){
	int ws = 0 ;
	while(u!=0){
		ws++;
		u/=10;
	}
	
	return ws;
}

struct node{
	ll val,step;
};

int bfs(){
	queue<node> q;
	q.push({x,1});
	mp[x] = 1;
	
	while(!q.empty()){
		auto t = q.front();
		q.pop();
		
		vector<int> v;
		
		ll temp  = t.val;
		while(temp!=0){
			v.pb(temp%10);
			temp/=10;
		}	
		
		for(auto u : v){
			if(u == 1 || !u) continue;
			// cout<<u<<" " << t.val<<endl;
			
			ll tt = u*t.val;
			ll ws = get(tt);
			
		
			if(mp[tt]) continue;
			
			mp[tt] = 1;
				
			
			
			if(ws > n)break;
			
			if(ws == n){
				//cout<<tt<<" "<<ws<<" "<<x<<endl;
				
				return t.step;
			}
			q.push({tt,t.step+1});
		}
	}
}

void solve(){
	cin>>n>>x;
	if(x == 1){
		if(n == 1) cout<<0<<endl;
		else cout<<-1<<endl;
		return;
	}
	
	int flag = 0 ;
	int t = x;
	while(t){
		int r = t%10;
		if(r!=0 && r!=1){
			flag =  1;
			break;
		}
		t/=10;
		
	}
	
	if(!flag){
		cout<<-1<<endl;
		return;
	}
	cout<<bfs()<<endl;
}

signed main(){
    //int t;cin>>t;while(t--)
    solve();
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值