Educational Codeforces Round 137 (Rated for Div. 2)(A~D)

更好的阅读体验 \color{red}{更好的阅读体验} 更好的阅读体验


A. Password


Origional Link

题目大意

  • 给定 n n n 0 ∼ 9 0\sim 9 09 之间不能使用的数字,保证剩余的数大于 2 2 2
  • 任意两个数子组合,每个数字可使用两次,组成一个四位密码。
  • 求在剩余的可选数字中,能组成的密码数量。

思想

  • 签到题。
  • 任意两个数字可组成的密码数量固定为 6 6 6
  • 则总数量为剩余数字中的两两组合的数量乘 6 6 6
  • 即设剩余的数的数量为 x = 10 − n x = 10 - n x=10n,总密码数为 x × ( x − 1 ) 2 \frac{x\times (x - 1)}{2} 2x×(x1).

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define re register
#define fi first
#define se second
#define endl '\n'

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const int N = 1e6 + 3;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-6, PI = acos(-1);

void solve(){

    int n; cin >> n;
    for(int i = 0; i < n; i ++){
        int x; cin >> x;
    }
    n = 10 - n;
    cout << 6 * n * (n - 1) / 2 << endl;

}

int main(){

    IOS;

    int _ = 1;

    cin >> _;

    while(_ --){
        solve();
    }

    return 0;

}

B. Permutation Value


Origional Link

题目大意

  • 给定一个长度为 n n n 的排列。
  • 定义其一个连续的子序列也为一种排列。
  • 构造一个排列使得满足上述条件的子序列的数量最少。
  • 输出任意满足条件的序列即可。

思想

  • 构造。
  • 只需要将 1 1 1 提到最前面,然后倒序输出剩余数即可。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define re register
#define fi first
#define se second
#define endl '\n'

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const int N = 1e6 + 3;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-6, PI = acos(-1);

void solve(){

    int n; cin >> n;
    cout << 1 << ' ';
    for(int i = n; i >= 2; i --) cout << i << ' ';
    cout << endl;

}

int main(){

    IOS;

    int _ = 1;

    cin >> _;

    while(_ --){
        solve();
    }

    return 0;

}

C. Save the Magazines


Origional Link

题目大意

  • 给定一个长为 n n n 且只包含 0 , 1 0,1 0,1 的字符串 s s s 1 1 1 表示 a i a_i ai 有盖,反之则无。
  • 接下来给出 a i a_i ai 个箱子内部所的含杂志数量,雨会淋湿没有盖盖子的箱子里的所有杂志。
  • 每个有盖子的箱子仅可操作一次,将盖子移动到 a i − 1 a_i-1 ai1 上。
  • 求最佳方案下最大能保护的杂志数量。

思想

  • 贪心。
  • 对于某个连续的 1 1 1 的区间 ( i , j ) (i,j) (i,j),我们可以移动的盖子范围在 a i − 1 ∼ j a_{i-1}\sim j ai1j,那么在区间 ( i − 1 , j ) (i-1,j) (i1,j) 中必然存在一个箱子没有盖子。
  • 故需要将区间 ( i − 1 , j ) (i-1,j) (i1,j) 中所含杂志数量最少的箱子的盖子移除,提供给没有盖子的箱子。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define re register
#define fi first
#define se second
#define endl '\n'

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const int N = 1e6 + 3;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-6, PI = acos(-1);

int a[N];

void solve(){

    int n; cin >> n;
    string s; cin >> s;
    for(int i = 0; i < n; i ++) cin >> a[i];

    LL sum = 0;

    int pos = s.find("1");

    // cout << pos << endl;
    if(pos == -1){
        cout << 0 << endl;
        return ;
    }

    for(int i = pos; i < n; i ++){
        if(s[i] == '1'){
            int cnt = 1;
            int t = a[i];
            sum += t;
            for(int j = i + 1; j < n; j ++){
                if(s[j] == '0') break;
                else cnt ++;
                t = min(t, a[j]);
                sum += a[j];
            }
            if(i - 1 >= 0){
                int p = a[i - 1];
                if(p > t) sum += p - t;
            }
            i += cnt - 1;
        }
    }

    cout << sum << endl;

}

int main(){

    IOS;

    int _ = 1;

    cin >> _;

    while(_ --){
        solve();
    }

    return 0;

}

D. Problem with Random Tests


Origional Link

题目大意

  • 给定一个只包含 0 , 1 0,1 0,1 的序列。
  • 可以通过一个字串与其按位“或”运算得到一个新的 0 , 1 0,1 0,1 序列。
  • 求如何操作使得该序列的二进制数最大。

思想

  • 贪心,枚举。
  • 该题的数据具有随机性。
  • 贪心发现,两个字符一定是从某一点位置开始,其中一个字符右移几个位置,然后或运算。
  • 那么我们需要从第一个出现的 0 0 0 的位置开始“或”运算,然后暴力匹配即可。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define IOS ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define re register
#define fi first
#define se second
#define endl '\n'

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const int N = 1e6 + 3;
const int INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-6, PI = acos(-1);

int a[N];

void solve(){
    
    int n; cin >> n;
    string s; cin >> s;
    s = " " + s;
    
    int pos = 1;
    bool flag = false;
    
    for(int i = 1; i <= n ; i ++ ){
        if(s[i] == '1') flag = true;
        if(flag && s[i] == '0'){
            pos = i;
            break;
        }
    }

    int st = pos;
    int len = n - pos + 1;
    string ans = s;
    
    for(int i = 1; i < st ; i ++ ){
        for(int j = i + len - 1; j <= n ; j ++ ){
            string temp = s;
            for(int k = n - len + 1, u = i ; u <= j ; u ++ , k ++ ) 
                if(s[u] == '1') temp[k] = '1';
            ans = max(ans, temp);
        }
    }
    
    flag = false;
    for(int i = 1; i <= n ; i ++ ){
        if(ans[i] == '1') flag = true;
        if(flag) cout << ans[i];
    }
    if(!flag) cout << 0;
    cout << endl;
}

int main(){

    IOS;

    int _ = 1;

    // cin >> _;

    while(_ --){
        solve();
    }

    return 0;

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪漫主义狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值