牛客周赛 Round 65

感觉是6道签到

A-超市 

思路 

全部买最小的那一个就行 

代码

void solve() {
   ll n,a,b;
    cin>>n>>a>>b;
    if(a>b){
        swap(a,b);
    }
    ll x=n/a+(n%a)/b;
    cout<<x;
}

B-雨幕 

思路 

暴力枚举所有的2*2空间即可 

代码 

void solve() {
    ll n, m;
    cin >> n >> m;
    vector<vector<char>>arr(n + 2, vector<char>(m + 2));
    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> arr[i][j];
        }
    }
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < m; j++) {
            if (arr[i][j] == '*' && arr[i][j + 1] == '*' && arr[i + 1][j + 1] == '*' && arr[i + 1][j] == '*') {
                ans++;
            }
        }
    }
    cout << ans;
}

 C-闺蜜 

思路

因为一定是偶数并且采取最优秀的策略的话,明显就是最后一次我将自己的最小值和对面的最大值替换即可

 代码

ll arr[20020];
void solve() {
    ll n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>arr[i];
    }
    sort(arr+1,arr+1+n,cmp2);
    swap(arr[1],arr[n]);
    ll sum1=0;
    ll sum2=0;
    for(int i=1;i<=n;i++){
        if(i&1){
            sum1+=arr[i];
        }
        else{
            sum2+=arr[i];
        }
    }
    if(sum1>sum2){
        cout<<"kou";
    }
    else if(sum1<sum2){
        cout<<"yukari";
    }
    else{
        cout<<"draw";
    }
}

D-医生 

思路 

我们注意道k<=10,就比较容易联想到子集枚举,那么我们对于每一个病人,去思考每一个子集能否给他医治好就可以了 ,在能医治好的里面取最小值

 代码 

void solve() {
    ll n, m;
    cin >> n >> m;
    vector<ll>arr(n + 2);
    for (int i = 1; i <= n; i++) {
        ll sum = 0;
        for (int j = 0; j < m; j++) {
            char f;
            cin >> f;
            if (f == '1') {
                sum = sum | (1 << j);
            }
        }
        arr[i] = sum;
    }
    ll k;
    cin >> k;
    vector<ll>brr(k + 2);
    for (int i = 0; i < k; i++) {
        ll sum = 0;
        for (int j = 0; j < m; j++) {
            char f;
            cin >> f;
            if (f == '1') {
                sum = sum | (1 << j);
            }
        }
        brr[i] = sum;
    }
    ll u = 1 << k;
    u--;
    
    for (int i = 1; i <= n; i++) {
        ll maxx = 1e9;
        for (int j = 0; j <= u; j++) {
            ll op = check(j);
            ll sum = 0;
            for (int o = 0; o < k; o++) {
                if ((1 << o) & j) {
                    sum = sum | brr[o];
                }
            }
            if ((sum & arr[i] )== arr[i]) {
                maxx = min(maxx, op);
            }
        }
        if (maxx == 1e9) {
            cout << "-1";
        }
        else {
            cout << maxx;
        }
        cout << endl;
    }
}

E-降温easy 

思路 

感觉跟f完全是一样的,我们先考虑最大的,如果我们目前是1 -999 -999 0,那么我们一定让第一个-999为前面的1去减去x的值,这样可以让当前最you,那么如果小于-50,就让当前点变成50就可以了,最大增大与后面一位的差值,最后统计即可,最小的情况就是x-1就可以了 

代码 

void solve() {
    ll n, x;
    cin >> n >> x;
    vector<ll>arr(n + 2);
    vector<ll>brr(n + 2);
    for (int i = 1; i <= n; i++) {
        cin >> arr[i];
        brr[i] = arr[i];
    }
    if (arr[1] == -999) {
        arr[1] = 50;
        brr[1] = -50;
    }
    for (int i = 2; i <= n; i++) {
        if (arr[i] == -999) {
            arr[i] = arr[i - 1] - x;
            if (arr[i] < -50) {
                arr[i] = 50;
            }
        }
        if (brr[i] == -999) {
            brr[i] = brr[i - 1] - (x - 1);
            if (brr[i] < -50) {
                brr[i] = -50;
            }
        }
    }
    ll sum1 = 0;
    ll sum2 = 0;
    for (int i = 2; i <= n; i++) {
        if (arr[i - 1] - arr[i] >= x) {
            sum1++;
        }
        if (brr[i - 1] - brr[i] >= x) {
            sum2++;
        }
    }
    cout << sum1 << " " << sum2;
 
}

 F-降温hard

思路 

跟e一样 

代码 

void solve() {
    ll n, x;
    cin >> n >> x;
    vector<ll>arr(n + 2);
    vector<ll>brr(n + 2);
    for (int i = 1; i <= n; i++) {
        cin >> arr[i];
        brr[i] = arr[i];
    }
    ll a = 5e8;
    ll b = -999999999;
    if (arr[1] == b) {
        arr[1] = 5e8;
        brr[1] = -5e8;
    }
    for (int i = 2; i <= n; i++) {
        if (arr[i] == b) {
            arr[i] = arr[i - 1] - x;
            if (arr[i] < -a) {
                arr[i] = a;
            }
        }
        if (brr[i] == b) {
            brr[i] = brr[i - 1] - (x - 1);
            if (brr[i] < -a) {
                brr[i] = -a;
            }
        }
    }
    ll sum1 = 0;
    ll sum2 = 0;
    for (int i = 2; i <= n; i++) {
        if (arr[i - 1] - arr[i] >= x) {
            sum1++;
        }
        if (brr[i - 1] - brr[i] >= x) {
            sum2++;
        }
    }
    cout << sum1 << " " << sum2;

}

 G-乌鸦 

思路 

如果m/n >= 1,我们选出 r = n+m%n 只用来分配,否则直接把所有m用来分配。

分配的方法是,先进行第一轮放置,根据r和n的奇偶性,间隔选出若干位置(奇数位或偶数位),放置一个乌鸦。

但是需要满足的条件是放置后剩余的r为偶数。

如果n为偶数,放置在奇数位置和偶数位置是一样的,我们无法左右放置后剩余的r值。

如果n为奇数,此时:
如果r为奇数,且n/2为奇数,必须放置在2,4...n-1;
如果r为偶数,且n/2为奇数,必须放置在1,3...n;
如果r为奇数,且n/2为偶数,必须放置在2,4...n-1;
如果r为偶数,且n/2为偶数,必须放置在1,3...n。

如果不能保证放置之后剩余的乌鸦数r为非负偶数,则说明一定不行,输出-1。

然后进行第二轮放置。对于剩余的偶数r只乌鸦,从和第一轮相反的位置间隔放置即可。例如第一轮放置在奇数位置,则此轮放置在偶数位置。

如果还有剩余,再进行第三轮放置。从和第一轮相同的位置间隔放置即可。例如第一轮放置在奇数位置,则此轮仍放置在奇数位置。

因为 n+m%n 一定在 n 和 n*2-1 之间,而我们的三轮放置最多能放 n/2 + n*2 只乌鸦,所以一定能放完。

代码


ll a[200200];
void solve() {
    int n;
    ll m;
    cin >> n >> m;
    ll b = m / n - 1;
    int r;
    if (b > 0) {
        for (int i = 1; i <= n; i++)
            a[i] = b;
        r = n + m % n;
    }
    else {
        r = m;
    }
    int s = r % 2 == 0 && n / 2 % 2 || r % 2 && n / 2 % 2 == 0 ? 1 : 2;
    r -= s == 1 && n % 2 ? n / 2 + 1 : n / 2;
    if (r < 0 || r % 2) {
        cout << -1 << '\n';
        return;
    }
    for (int i = s; i <= n; i += 2) {
        a[i]++;
    }
    for (int i = (s == 2 ? 1 : 2); i <= n; i += 2) {
        a[i] += 2;
        r -= 2;
        if (r == 0) {
            for (int i = 1; i <= n; i++)
                cout << a[i] << ' ';
            cout << '\n';
            return;
        }
    }
    for (int i = s; i <= n; i += 2) {
        a[i] += 2;
        r -= 2;
        if (r == 0) {
            for (int i = 1; i <= n; i++)
                cout << a[i] << ' ';
            cout << '\n';
            return;
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值