AtCoder Beginner Contest 227

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 227相关的知识,希望对你有一定的参考价值。

C - ABC conjecture

题意:

给定一个 N N N,现在问有多少个三元组 ( A , B , C ) (A,B,C) (A,B,C), A ≤ B ≤ C A≤B≤C ABC A B C ≤ N ABC≤N ABCN

思路:

直接暴力枚举,时间复杂度 O ( N 2 3 ) O(N^\\frac23) O(N32),枚举A和B然后算出有多少个C

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int s[N];
#define ll long long
int main() 
    ll n;
    cin >> n;
    ll res = 0;
    for (ll i = 1; i * i * i <= n; i++) 
        for (ll j = i; i * j * j <= n; j++) 
            res += n / i / j - j + 1;
        
    
    cout << res << endl;

D - Project Planning.

题意:

给一个长度为 N N N的数列, A 1 . . . . A N A_1....A_N A1....AN, A i ≥ 1 A_i≥1 Ai1,现在每次选 K K K个数减去 1 1 1,每个数只能被减到 0 0 0,问整个数列最多能操作几次

思路:

假设可以操作 P P P次,现在令 s u m = sum= sum= ∑ i = 1 n m i n ( P , A i ) \\sum_i=1^n min(P,A_i)\\qquad i=1nmin(P,Ai),
如果 P × K > s u m P×K>sum P×K>sum,那么很明显是不够减的,所以一定不成立
可以假设当 P × K ≤ s u m P×K≤sum P×Ksum时,我们可以操作 P P P
每次操作的策略始终都是拿最大的 K K K个数
假设 ≥ P ≥P P的个数为 n u m num num
1. 如果 n u m ≥ K num≥K numK,那么此时一定是满足 P × K > s u m P×K>sum P×K>sum
2. 如果 n u m = K − 1 num=K-1 num=K1,那么为了保证不等式剩下的数的和一定 ≥ P ≥P P,又由于大小 < P <P <P,所以个数一定 ≥ 2 ≥2 2 且最大是 P − 1 P-1 P1,每次拿前 K − 1 K-1 K1大的数,剩下的一个数从小数中拿,由于剩下的数的和一定 ≥ P ≥P P,所以最后拿完 P P P次后,拿出来的数的和一定满足 P × K > s u m P×K>sum P×K>sum
3. 如果 n u m = K − 2 num=K-2 num=K2,那么为了保证不等式剩下的数的和一定 ≥ P ≥P P
又由于大小 < P <P <P,所以个数一定 ≥ 3 ≥3 3,且最大是 P − 1 P-1 P1,每次拿前 K − 2 K-2 K2大的数,剩下的一个数从小数中拿,第一次拿一定成功,拿完后,开始第二次拿,此时不等式就是 s u m − k ≥ P ∗ K − K sum-k≥P*K-K sumkPKK,如果第二次拿失败了,说明剩下的 3 3 3个数中,有至少2个数是 0 0 0,这就说明之前有两个数是 1 1 1,且这两个数是剩下的数中最大的两个,那么就说明剩下的三个数是最大情况就是 1,1,0,由于而这与中间推导的个数一定 > = 3 >=3 >=3,所以第二次拿一定是可以的,…一直推导到可以拿 P P P

K-1. 如果 n u m = 0 num=0 num=0,…个数一定 ≥ K − 1 ≥K-1 K1,…按照上面归纳总结即可
最后按照不等式 P × K ≤ s u m P×K≤sum P×Ksum,来二分即可
洛谷也有别的结论及证明 link.

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define ll long long
ll a[N];
int n, k;
bool check(ll x) 
    ll sum = 0;
    ll cnt = 0;
    for (int i = 1; i <= n; i++) 
        sum += min(x, a[i]);
    
    return sum >= x * k;

int main() 
    cin >> n >> k;
    for (int i = 1; i <= n; i++) 
        cin >> a[i];
    
    ll l = 0, r = 1e18 / k;
    while (l < r) 
        ll mid = (l + r + 1) / 2;
        if (check(mid)) 
            l = mid;
         else 
            r = mid - 1;
        
    
    cout << l << endl;

E - Swap

题意:

给定一个只有 K , E , Y K,E,Y K,E,Y字母的一个字符串,现在问最多能交换相邻字符串 K K K次,问能形成多少种字符串

思路:

原字符串定义为 A A A,变换后的字符串定义为 B B B
定义 d p ( i , e , y , x ) dp(i,e,y,x) dp(i,e,y,x) B B B字符串前 i i i位有 e 个 E e个E eE y 个 Y y个Y yY 需要操作 x x x次才能变成与 A A A字符串前 i − e − y 个 K i-e-y个K ieyK e 个 E e个E eE y 个 Y y个Y yY的相对顺序一致
最终就是 d p ( l e n , e c n t , y c n t , i ) dp(len,ecnt,ycnt,i) dp(len,ecnt,ycnt,i)从0到k的累加
那么此时已知 d p ( i , e , y , x ) dp(i,e,y,x) dp(i,e,y,x)的话,看对 d p ( i + 1 ) dp(i+1) dp(i+1)产生什么影响即可

在当前状态下,如果末尾来了一个 K K K,这是第 i − e − y i-e-y iey K K K为了保证相对位置一样,就需要新来的 K K K与原序列的第 i − e − y i-e-y ieAtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242