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
定义为长度为
的好序列,现给定一组数组,你可以选中其子序列,同时将其中的数减去若干,组成一组好序列。求好序列的最大长度。
二分求长度,从头开始遍历,然后判断能否形成这个好序列,首先从头到尾尽可能的组成一组好序列,若到某个数时无法和前面的数组成好序列,那就将这个数变成新序列的第位,其中
为这个数的值,这样做必然是最优的。
// 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,首先可以发现,因此位数之和应当小于
。所以我们可以钦定位数和,然后求出每个位数和分别有多少个数满足条件。
定义代表了数的前
位,各个位数之和为
,余数为
的和。其中
表示是否为上界(其中0代表未达到上界,1代表还处于上界之中)。每一轮都是将新的数插入之前数的最后,假设加的数为
,那么新的余数
就变成了
模上位数和。最终答案加上第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
题意:给定一个长为,宽为
的二维数组,其中每次操作能够将长为
,宽为
的块翻转180°。求最终能否变成一个1,2,3,4,5....的顺序数组。限定操作最多为20次。
参考图片
思路:(折半搜索)首先肯定考虑DFS遍历所有情况,然后每一轮的情况共有4种,那么总共的复杂度为肯定是超的。因此考虑从头开始dfs和从尾开始dfs,这样两次dfs的时间复杂度均为
,然后若有重复的,那么就代表能够从头走到尾,记录一下答案即可。单纯考察折半搜索,就是写起来比较复杂
// 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;
}