题解 | #A - E#

双子爆破者

https://ac.nowcoder.com/acm/contest/41173/A

牛客小白月赛58 A - E

https://ac.nowcoder.com/acm/contest/41173

A - 双子爆破者

直接套公式

#include <bits/stdc++.h>

using namespace std;

void solve () {
    double M, m, v;
    cin >> M >> m >> v;
    cout << fixed << setprecision (3) << 1.0*m*v/(M-m) << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --)    solve ();
}

B - 牛原子

模拟题,但是读题读了贼久

题意:按照 1s 2s 2p 3s 3p 4s 3d 4p 5s 4d 5p 6s 4f 5d 6p 7s 5f 6d 7p 的顺序进行原子排列,s类电子亚层容量为 2,p 类电子亚层容量为 6,d 类电子亚层容量为 10,f 类电子亚层容量为 14,排满了就放下一层。最后要按照数字升序,字母“spdf” 的顺序来排列。

嗯模拟即可

#include <bits/stdc++.h>
#define ll long long

using namespace std;
//spdf
string s[] = {"1s", "2s", "2p", "3s", "3p", "4s", "3d", "4p", "5s", "4d", "5p", "6s", "4f", "5d", "6p", "7s", "5f", "6d", "7p"};
//string s[] = {"1s", "2s", "2p", "3s", "3p", "3d", "4s", "4p", "4d", "4f", "5s", "5p", "5d", "5f", "6s", "6p", "6d", "7s", "7p"};
map<char, int> mp = {{'s', 1}, {'p', 2}, {'d', 3}, {'f', 4}};

bool cmp (string a, string b) {
    if (a[0] != b[0])   return a[0] < b[0];
    return mp[a[1]] < mp[b[1]];
}

void solve () {
    int n;
    scanf ("%d", &n);
    vector <string> v;
    for (int i = 0; i < 19; i++) {
        int dx = 0;
        if (s[i][1] == 's')     dx = 2;
        else if (s[i][1] == 'p')    dx = 6;
        else if (s[i][1] == 'f')    dx = 14;
        else    dx = 10;
        if (n - dx >= 0)    n -= dx, v.push_back (s[i] + to_string(dx));
        else    v.push_back (s[i] + to_string(n)), n = 0;
        if (n <= 0) break;
    }
    sort (v.begin (), v.end (), cmp);
    for (auto i : v)    cout << i << ' ';
    cout << endl;
}

signed main () {
    int t;
    scanf ("%d", &t);
    while (t --)    solve ();
}

//s类电子亚层容量为 2,p 类电子亚层容量为 6,d 类电子亚层容量为 10,f 类电子亚层容量为 14
//1s 2s 2p 3s 3p 4s 3d 4p 5s 4d 5p 6s 4f 5d 6p 7s 5f 6d 7p

C- 牛牛

因为读不懂题B先出的C

题意:就相当于在n个数当中挑出2个数,使得剩下的数之和 % m == 0,简单做一下公式变换即得:

(sum-ai-aj) % 10 = 0得,

即,枚举 ai,找到一个满足上述条件的 aj 即可,注意 i 不等于 j

用map查找 nlogn

#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 2e5 + 5;
int a[N];

void solve () {
    map <int, int> s;
    int n, m;
    ll sum = 0;
    scanf ("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf ("%d", &a[i]);
        sum += a[i];
        s[a[i] % m] ++;
    }
    for (int i = 1; i <= n; i++) {
        ll x = (sum - a[i]) % m;
        if (s[x]) { //并且不能是自身
        if (s[x] == 1 && (a[i] % m == x))   continue;
            ll ans = sum % m;
            if (ans == 0)   ans = m;
            printf ("%lld\n", ans);
            return ;
        }
    }
    printf ("0\n");
}

signed main () {
    int t;
    scanf ("%d", &t);
    while (t --)    solve ();
}

//剔除两张,剩下的要是10的倍数

D - 数学考试

按照题意进行背包dp

因为空间限制很严格,所以要滚动数组

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int N = 1e4 + 5, M = 5e3 + 5;
int f[M][2], n, k, ans; //空间要求很严格所以要滚动数组

void solve () {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        int a, b, q, w;
        cin >> a >> b >> q >> w;
        for (int j = 0; j <= k; j++)    f[j][i & 1] = 0;
        for (int j = 0; j <= k; j++) {
            int dx = f[j][(i-1) & 1];
            if (j <= b)     dx += a * j;
            //三种策略
            if (j + q <= k)     f[j + q][i & 1] = max (f[j + q][i & 1], dx);
            if (j - w >= 0)     f[j - w][i & 1] = max (f[j - w][i & 1], dx);
            f[j][i & 1] = max (f[j][i & 1], dx); //无条件转移
        }
    }
    for (int j = 0; j <= k; j++)    ans = max (ans, f[j][n & 1]);
    cout << ans;
}

signed main () {
    solve ();
}

E - 法力无边

学习牛客竞赛官方题解

【技巧】位运算 经典map + 前缀和

*转换为加法 —— 异或:%2;同或 %2 + 1 *

如此,就可以利用前缀和,即 M[i][j]=((ai+...+aj) + j-i) % 2 = 1

化成比较好看的通项性质,则有:(sum[j]+j) 同余 (sum[i-1] + i-1) (mod 2)

可令 d[i] = sum[i] - i,则有 d[j] 同余 d[i-1] (mod 2)

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int N = 25;
int sum[N][2], n, m;

void solve () {
    cin >> n >> m;
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        int x;  cin >> x;
        for (int j = 0; j < m; j++) {
            if ((x >> j) & 1)   sum[j][1] ++;
            else    swap (sum[j][0], sum[j][1]), sum[j][0] ++;
            ans += (1 << j) * sum[j][1];
        }
    }
    cout << ans;
}

signed main () {
    solve ();
}

F待补

全部评论
救命,第二题一直陷入逻辑死循环,就是没有走出来,一道题我写了1个半小时
点赞 回复 分享
发布于 2022-10-02 21:17 江西
下次再也不这么搞了
点赞 回复 分享
发布于 2022-10-02 21:17 江西
你的c题题解中的ans应该是 (ai+aj )% m ,为啥sum也能过,哈哈
点赞 回复 分享
发布于 2022-10-03 11:40 江西

相关推荐

粗心的雪碧不放弃:纯学历问题,我这几个月也是一直优化自己的简历,后来发现优化到我自己都觉得牛逼的时候,发现面试数量也没有提升,真就纯学历问题
点赞 评论 收藏
分享
小红书 后端开发 总包n+8w+期权
点赞 评论 收藏
分享
评论
3
收藏
分享
牛客网
牛客企业服务