牛客练习赛80

牛客练习赛80

总结: A了三题,凭着手速冲上了前50,这场的神仙估计都参加春招去了,榜首才出了4题,活久见。

A. 加密
在这里插入图片描述
很常规的简单模拟,大方向是先算出由1形成的段共几段,然后通过一次反转至多可以减少掉一个1子串。考虑几种情况:

  1. 当两个连续的1形成的块中间隔了超过1个0时,将中间的0直接反之显然没什么意义。
  2. 当两个连续的1形成的块中间隔了1个0时,将中间的0反转即可减少一个子串。
  3. 当有一个1两边都是0的时候,将这个1反转也能减少1个子串。
  4. 当1出现在最左侧或者最右侧的时候,只要旁边的是0也能消除一个子串。

代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f,x) memset(f,x,sizeof(f))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
#define pk push_back
using namespace std;

const int M = 1e6+5;
const int N = 1e6+5;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
int m, n;
char s[N];

int main( ){
    while( scanf( "%s", s ) != EOF ){
        n = strlen(s);
        bool flag = 0;
        int i = 0, cnt = 0;
        
     
        while( i < n ){
            if( s[i] == '0' ){
                if( i && i < n-1 && s[i-1] == '1' && s[i+1] == '1')    
                    flag = 1;
                i++;
            }
            else{
                if( i && i < n-1 && s[i-1] == '0' && s[i+1] == '0' )
                    flag = 1;
                if( !i && s[i+1] == '0' )
                    flag = 1;
                if( i == n-1 && s[i-1] == '0' )
                    flag = 1;
                cnt++;
                while( i < n && s[i] == '1' )
                    i++;
            }
        }
        printf( "%d\n", cnt-flag );
    }
    return 0;
}

B. 卷积
在这里插入图片描述
很容易想到,当 i>2 时Ci必定为0,因为无论选哪两个数,都不可能满足未出现的最小的下标大于2。因此只需要讨论i = 0,1,2时的情况。

  1. i = 0时,可以选a中下标大于1的任何数和b中下标大于0的任何数
  2. i = 1时,有三种选法:{a[0],b[0]};{a[0],b[j]};{a[j],b[0]} 其中j > 1
  3. i = 2时,有两种选法:{a[0],b[2]};{a[2],b[0]}

代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f,x) memset(f,x,sizeof(f))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
#define pk push_back
using namespace std;

const int M = 1e5+5;
const int N = 1e5+5;
const ll MOD = 998244353;
const int INF = 0x3f3f3f3f;
int m, n;
ll a[N], b[N];


int main( ){
    while( scanf( "%d", &n ) != EOF ){
        ll suma = 0, sumb = 0;
        for( int i = 0; i < n; i++ ){
            scanf( "%lld", a+i );
            suma = (suma+a[i])%MOD;
        }
            
        for( int i = 0; i < n; i++ ){
            scanf( "%lld", b+i );
            sumb = (sumb+b[i])%MOD;
        }
            
        if( n == 1 ){
            printf( "0\n" );
            continue;
        }
        if( n == 2 ){
            printf( "%lld %lld\n", a[1]*b[1]%MOD, a[0]*b[0]%MOD );
            continue;
        }
        ll ans1 = ((suma-a[0]+MOD)%MOD)*((sumb-b[0]+MOD)%MOD)%MOD;
        ll tmp1 = (a[0]*b[0])%MOD;
        ll tmp2 = a[0]*(((sumb-b[0]+MOD)%MOD-b[1]+MOD)%MOD)%MOD;
        ll tmp3 = b[0]*(((suma-a[0]+MOD)%MOD-a[1]+MOD)%MOD)%MOD;
        ll ans2 = (tmp1+tmp2+tmp3)%MOD;
        ll ans3 = (a[0]*b[1]%MOD+a[1]*b[0]%MOD)%MOD;
        printf( "%lld %lld %lld", ans1, ans2, ans3 );
        for( int i = 3; i < n; i++ )
            printf( " 0" );
        printf( "\n" );
    }
    return 0;
}

C. 不降数
在这里插入图片描述
先可暴力打表,我自己是把n = 1,2,3,4,5下的答案打表打出来了,后面发现的规律是 f(n) = C(n+8, 8)。

代码:

#include <bits/stdc++.h>
#define ll long long
#define mem(f,x) memset(f,x,sizeof(f))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
#define pk push_back
using namespace std;

const int M = 1e6+5;
const int N = 1e6+5;
const int MOD = 100019;
const ll inv = 78440;
const int INF = 0x3f3f3f3f;
ll m, n;

ll q_pow( ll x, ll y ){
    x %= MOD;
    ll ret = 1;
    while( y ){
        if( y&1 ) ret = (ret*x)%MOD;
        x = x*x%MOD;
        y >>= 1;
    }
    return ret;
}
int main( ){
    /*ll fm = 1;
    for( int i = 1; i <= 8; i++ )
        fm = fm*i%MOD;
    cout << q_pow( fm, MOD-2 ) << endl;*/
    while( scanf( "%lld", &n ) != EOF ){
        ll sum = 1;
        for( int i = 1; i <= 8; i++ )
            sum = sum*(n+i)%MOD;
        sum = sum*inv%MOD;
        printf( "%lld\n", sum );
    }
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值