AtCoder ABC 336(A~F)

A - Long Loong

        模拟

// Problem: A - Long Loong
// Contest: AtCoder - AtCoder Beginner Contest 336
// URL: https://atcoder.jp/contests/abc336/tasks/abc336_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){
	for(int i = 0 ; i <= n ; i ++){
		a[i] = 0;
	}
}
void solve() 
{
	cin >> n;
	string s = "";
	s += 'L';
	for(int i = 0 ; i < n ; i ++){
		s += 'o';
	}
	s += "ng";
	cout << s;
}            
int main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int t=1;
//	cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

B - CTZ

        还是模拟

// Problem: B - CTZ
// Contest: AtCoder - AtCoder Beginner Contest 336
// URL: https://atcoder.jp/contests/abc336/tasks/abc336_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){
	for(int i = 0 ; i <= n ; i ++){
		a[i] = 0;
	}
}
void solve() 
{
	int ans = 0;
	cin >> n;
	while(n){
		if(n & 1)
			break;
		else
			ans++;
		n/=2;
	}	
	cout << ans;
}            
int main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int t=1;
	//cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

C - Even Digits

        找出由0 , 2 , 4 , 6 , 8 组成的第x大数,模拟(注意一开始不能取0 , 因此其实是一个开头为4,其余都是5的进制数)。

// Problem: C - Even Digits
// Contest: AtCoder - AtCoder Beginner Contest 336
// URL: https://atcoder.jp/contests/abc336/tasks/abc336_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){
	for(int i = 0 ; i <= n ; i ++){
		a[i] = 0;
	}
}
int mask[5] = {0 , 2 , 4 , 6 , 8};
void solve() 
{
	LL n;
	cin >> n;
	n--;
	LL k = 1;
	while(k * 5 <= n){
		k *= 5;
	}
	while(k > 0){
		int t = n / k;
		cout << mask[t];
		n -= t * k;
		k /= 5;
	}
}            
int main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int t=1;
	//cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

D - Pyramid

        定义1, 2, 3...k-1, k, k-1...3,2,1为长度为k的好序列,现给定一组数组,你可以选中其子序列,同时将其中的数减去若干,组成一组好序列。求好序列的最大长度。

        二分求长度,从头开始遍历,然后判断能否形成这个好序列,首先从头到尾尽可能的组成一组好序列,若到某个数时无法和前面的数组成好序列,那就将这个数变成新序列的第a_{i}位,其中a_{i}为这个数的值,这样做必然是最优的。

        

// Problem: D - Pyramid
// Contest: AtCoder - AtCoder Beginner Contest 336
// URL: https://atcoder.jp/contests/abc336/tasks/abc336_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){
	for(int i = 0 ; i <= n ; i ++){
		a[i] = 0;
	}
}
void solve() 
{
	int n;
	cin >> n;
	for(int i = 0 ; i < n ; i ++){
		cin >> a[i];
	}	
	int l = 1 , r = (n + 1) / 2;
	auto check = [&] (int len){
		int cnt = 0;
		for(int i = 0 ; i < n ; i ++){
			if(cnt < len){
				if(a[i] >= cnt + 1){
					cnt++;
				}
				else{
					cnt = a[i];
				}
			}
			else{
				if(a[i] >= len - (cnt - len + 1)){
					cnt++;
				}
				else{
					cnt = a[i];
				}
			}
			if(cnt >= len * 2 - 1){
				return true;
			}
		}
		return false;
	};
	while(l < r){
		int mid = (l + r + 1) / 2;
		if(check(mid)){
			l = mid;
		}
		else{
			r = mid - 1;
		}
	}
	cout << l << endl;
}            
int main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int t=1;
//	cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

E - Digit Sum Divisible

        题意:从1~N,输出其中各个位数之和能够整除其的数量。

        思路:数位DP,首先可以发现N\leq 1e14,因此位数之和应当小于9 * 14。所以我们可以钦定位数和,然后求出每个位数和分别有多少个数满足条件。

        定义dp[i][sum][res][st]代表了数的前i位,各个位数之和为sum,余数为res的和。其中st表示是否为上界(其中0代表未达到上界,1代表还处于上界之中)。每一轮都是将新的数插入之前数的最后,假设加的数为num,那么新的余数res就变成了res * 10 + num 模上位数和。最终答案加上第N的位数位,总和为钦定的位数和,余数为0,状态为0或者1的总数。

// Problem: E - Digit Sum Divisible
// Contest: AtCoder - AtCoder Beginner Contest 336
// URL: https://atcoder.jp/contests/abc336/tasks/abc336_e
// Memory Limit: 1024 MB
// Time Limit: 10000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
#define int long long 
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int n , m;
int dp[20][200][200][2];//第i位,和为x,余数为y的个数,是否为上界的情况
vector<int>a(N , 0);
void init(int n){
	for(int i = 0 ; i <= n ; i ++){
		a[i] = 0;
	}
}
void solve() 
{
	string n;
	cin >> n;
	int len = n.size();
	LL ans = 0;
	for(int i = 1 ; i <= 9 * 14 ; i ++){//钦定位数和
		memset(dp , 0 , sizeof dp);
		dp[0][0][0][1] = 1;
		for(int j = 1 ; j <= len ; j ++){//14
			for(int k = 0 ; k <= 9 * 14 ; k ++){//总和100
				for(int num = 0 ; num <= 9 ; num ++){
					if(k + num > i){
						continue;
					}
					for(int st = 0 ; st < 2 ; st ++){
						if(st && num > (n[j - 1] - '0')){
							continue;
						}
						for(int res = 0 ; res < i ; res ++){
							int now_res = (res * 10 + num) % i;
							dp[j][k + num][now_res][(st && (num == n[j - 1] - '0'))] += dp[j - 1][k][res][st];
						}
					}
				}
			}	
		}
		ans += dp[len][i][0][0] + dp[len][i][0][1];
	}
	cout <<ans;
}            
signed main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int t=1;
//	cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

F - Rotation Puzzle

        题意:给定一个长为h,宽为w的二维数组,其中每次操作能够将长为h-1,宽为w - 1的块翻转180°。求最终能否变成一个1,2,3,4,5....的顺序数组。限定操作最多为20次。

参考图片

        

        思路:(折半搜索)首先肯定考虑DFS遍历所有情况,然后每一轮的情况共有4种,那么总共的复杂度为O(4^{20})肯定是超的。因此考虑从头开始dfs和从尾开始dfs,这样两次dfs的时间复杂度均为 O(4^{10}),然后若有重复的,那么就代表能够从头走到尾,记录一下答案即可。单纯考察折半搜索,就是写起来比较复杂

// Problem: F - Rotation Puzzle
// Contest: AtCoder - AtCoder Beginner Contest 336
// URL: https://atcoder.jp/contests/abc336/tasks/abc336_f
// Memory Limit: 1024 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){
	for(int i = 0 ; i <= n ; i ++){
		a[i] = 0;
	}
}
int ans = 25;
map< vector<vector<int>> , int > mp;	
vector<vector<int>>s(9 , vector<int>(9 , 0));
void change(int l_min , int l_max ,int r_min , int r_max){
	for(int i = 0 ; i <= (r_max - r_min) ; i ++){
		int st = r_min + i;
		int en = r_max - i;
		if(st > en)
			break;
		else if(st == en){
			for(int j = 0 ; j <= (l_max - l_min) ; j ++){
				int ss = l_min + j;
				int ee = l_max - j;
				if(ss > ee)
					break;
				swap(s[st][ss] , s[en][ee]);
			}			
		}
		else{
			for(int j = 0 ; j <= (l_max - l_min) ; j ++){
				int ss = l_min + j;
				int ee = l_max - j;
				swap(s[st][ss] , s[en][ee]);
			}
		}
	}
}
void dfs(int step){
	if(step > 10)
		return;
	if(!mp.count(s)){
		mp[s] = step;
	}
	else{
		mp[s] = min(mp[s] , step);
	}

	change(0 , n - 2 , 0 , m - 2);
	dfs(step + 1);
	change(0 , n - 2 , 0 , m - 2);
	
	change(1 , n - 1 , 0 , m - 2);
	dfs(step + 1);
	change(1 , n - 1 , 0 , m - 2);
	
	change(0 , n - 2 , 1 , m - 1);
	dfs(step + 1);
	change(0 , n - 2 , 1 , m - 1);
	
	change(1 , n - 1 , 1 , m - 1);
	dfs(step + 1);
	change(1 , n - 1 , 1 , m - 1);	
}
void dfs2(int step){
	if(step > 10)
		return;
	if(mp.count(s)){
		ans = min(ans , step + mp[s]);
	}
	
	change(0 , n - 2 , 0 , m - 2);
	dfs2(step + 1);
	change(0 , n - 2 , 0 , m - 2);
	
	change(1 , n - 1 , 0 , m - 2);
	dfs2(step + 1);
	change(1 , n - 1 , 0 , m - 2);
	
	change(0 , n - 2 , 1 , m - 1);
	dfs2(step + 1);
	change(0 , n - 2 , 1 , m - 1);	
	
	change(1 , n - 1 , 1 , m - 1);
	dfs2(step + 1);
	change(1 , n - 1 , 1 , m - 1);	
}
void solve() 
{
	cin >> m >> n;
	int id = 1;
	for(int i = 0 ; i < m ; i ++){
		for(int j = 0 ; j <n ; j ++){
			cin >> s[i][j];
		}
	}

	dfs(0);
	id = 1;
	for(int i = 0 ; i < m ; i ++){
		for(int j = 0 ; j < n ; j ++){
			s[i][j] = id++;
		}
	}

	dfs2(0);
	if(ans == 25)
		cout << -1;
	else
		cout << ans;
}            
int main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int t=1;
	//cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值