牛客小白月赛71

发布时间 2023-04-24 19:36:02作者: PHarr

A 猫猫与广告

#include <bits/stdc++.h>
using namespace std;

int32_t main(){
    int a , b , c , d ;
    cin >> a >> b >> c >> d;
    if( a > b ) swap(a , b);
    if( c > d ) swap( c , d );
    if( a <= c && b <= d ) cout << "YES\n";
    else cout << "NO\n";
    return 0;
}

B 猫猫与密信

#include <bits/stdc++.h>
using namespace std;

int32_t main(){
    string s;
    cin >> s;
    if ( s.find("love") != -1 )cout << "YES\n";
    else if (s.find("lov") != -1) cout << "YES\n";
    else if (s.find("loe") != -1) cout << "YES\n";
    else if (s.find("lve") != -1) cout << "YES\n";
    else if (s.find("ove") != -1) cout << "YES\n";
    else cout << "NO\n";
    return 0;
}

C 猫猫与数列

其实就是按照题目操作就好了,但是精度问题把我整麻了,最后又 python 来解决了,感觉和电科校赛异曲同工了。

m = 10 ** 18

def power( x , y ) :
    ans = 1
    while( y > 0 ):
        # print( x , y , ans)
        if( y % 2 == 1 ) :
            ans = ans * x
            if( ans > m ) :
                # print( ans , m , " cnt")
                return ans
        y = y // 2
        x = x * x
        if( y > 0 and x > m ) :
            return x
    return ans


a = list(map( int, input().split(' ') ))
while a[-1] <= m :
    x = power( a[-2] , a[-1])
    a.append( x )

cnt = 0
for i in a :
    if( i <= m ) :
        cnt += 1
    else :
        print( cnt )

D 猫猫与主人

看了看答案的做法是离线回答询问。其实感觉还是蛮不好想的。

我的做法是首先把人按照\(d_i\)从小到大排序,对于每一只猫可以二分出最大的\(r\)满足\(a_i\ge d_r\),这样的话对于\(j\in[1,r]\)都满足了\(a_i\ge d_j\)现在要找是否存在\(j\)满足\(b_j\ge c_i\),满足的条件可以简化为\(\max(b_j)\)满足,这样的话实际上就是求区间最值,因为没有修改所以我使用 ST 表实现。

#include <bits/stdc++.h>
using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 2e5+5 , logN = 20;
int a[N] , c[N] , log_2[N] , f[N][logN+5];
pair<int,int> person[N];

int search( int l , int r ){
    int s = log_2[ r - l + 1 ];
    return max( f[l][s] , f[ r-(1<<s) + 1 ][s] );
}

int32_t main(){
    int n = read() , m = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    for( int i = 1 ; i <= n ; i ++ ) c[i] = read();

    for( int i = 1 ; i <= m ; i ++ ) person[i].second = read();
    for( int i = 1 ; i <= m ; i ++ ) person[i].first = read();
    sort( person +1 , person+1+m);

    log_2[0] = -1;
    for( int i = 1 ; i <= m ; i ++ )
        f[i][0] = person[i].second , log_2[i] = log_2[i>>1] + 1;

    for( int j = 1 ; j <= logN ; j ++ )
        for( int i = 1; i + (1<<j) - 1 <= m ; i ++ )
            f[i][j] = max( f[i][j-1] , f[i+(1<<j-1) ][j-1] );

    for( int i = 1 ; i <= n ; i ++ ){
        int l = 1 , r = m , mid , ans = 0;
        while( l <= r ){
            mid = ( l + r ) >> 1;
            if( person[mid].first <= a[i] ) ans = mid , l = mid + 1;
            else r = mid - 1;
        }
        if( ans == 0 ) {
            printf("-1 ");
            continue;
        }
        int t = search( 1 , ans );
        if( t >= c[i] ) printf("%lld " , t );
        else printf("-1 ");
    }
    return 0;
}

E 猫猫与数学

\(a > b\),根据更相减损术\(\gcd( a + c , b + c ) = \gcd( a - b , a + c )\)

现在要求最小的\(c\)满足$\gcd(a-b,a+c) \ne 1 $

考虑到\(a-b\)这个数字是\(10^{14}\),说明\(a-b\)的因子\(d\)最多有\(10^7\)级别个,我们可以枚举\(d\)使得\(\gcd(a-b,a+c)=d\)则要求\(a+c\)\(d\)的倍数。可以\(O(1)\)的算出最小的\(c\),这样复杂度就可以接受。

#include <bits/stdc++.h>

using namespace std;

#define int long long


int32_t main() {
    int a , b , d , res = 1e18;
    cin >> a >> b;
    if( a < b ) swap( a , b );
    d = a - b;
    if( d == 1 ){
        printf("-1\n");
        return 0;
    }else if( d == 0 ){
        if( a == 1 ) printf("1\n");
        else printf("0\n");
        return 0;
    }
    auto check = [&]( int x ){
        if( x == 1 ) return;
        if( a % x == 0 ) res = min( res , 0ll );
        else res = min( res , x - a % x );
    };

    for( int i = 1 , n = sqrt(d) ; i <= n ; i ++ ){
        if( d % i ) continue;
        check(i) , check(d/i);
    }
    printf("%lld\n" , res);
    return 0;
}

F 猫猫与宝石

对于前\(m\)项中的任意一项\(i\),产生的贡献是\(\frac 1 2 a_i\times E(c)\),然后我们考虑\(E(c)\)的值,先说\(E(c)\)要产生贡献的前提条件是什么?就是一定要选\(a_i\),除此之外的\(m-1\)项按照期望计算就是会选出\(\frac{m-1}{2}\)所以\(E(c)=\frac{m-1}2 + 1\)

所以前\(m\)项的答案就是\(\sum_{i=1}^{m} \frac 1 2 a_i (\frac{m-1} 2 + 1)=\frac{m+1}{4}\sum a_i\)

所以计算前缀和的时候就可以计算出答案。

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int mod = 998244353 , inv4 = 748683265;

int32_t main() {
    int n = read() , sum = 0;
    for( int i = 1 ; i <= n ; i ++ ){
        sum = ( sum + read() ) % mod;
        printf("%lld " , sum * (i+1) % mod * inv4 % mod );
    }
    return 0;
}