2019年牛客多校第1场 赛后总结

A题 :Equivalent Prefixes

 题意:就是给你两个有n个不同数的串,然后保证1-p区间内任选一个区间,使得区间中最小值的下标相同,找到最大的p值

 思路:我的思路是设置两个单调栈,然后每次的第i个数判断大小,放到栈顶(比它大的数弹出栈),当两个栈容量不同时,即不成立。

代码如下:

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

typedef long long ll;
const int maxn = 5e5 + 5;

int a[maxn], b[maxn];
stack<int>s1, s2;

int main(void)
{
    int n;
    while (~scanf("%d", &n)) {
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for (int i = 1; i <= n; i++)
            scanf("%d", &b[i]);

        while (s1.size())    s1.pop();
        while (s2.size())    s2.pop();

        int ans = 1;
        s1.push(a[1]);
        s2.push(b[1]);

        for (int i = 2; i <= n; i++) {
            while (s1.size() && s1.top() > a[i])
                s1.pop();
            s1.push(a[i]);
            while (s2.size() && s2.top() > b[i])
                s2.pop();
            s2.push(b[i]);

            if (s1.size() != s2.size())
                break;
            ans = i;
        }
        cout << ans << endl;
    }

    return 0;
}

B题:Integration

 题意:已知,求

这道题强行唤醒我的数学…但最终以失败告终…看了好几个巨巨的博客……这里感谢这位大佬的博客:2019牛客网暑期多校第一场B题

我们可以得到:

由数学归纳法,可得:

又因为

然后进行逆元,费马小定理

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

typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e3 + 10;
ll a[maxn];

ll qpow(ll a, ll b)
{
    ll res = 1;
    while (b) {
        if (b & 1)
            res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

int main(void)
{
    int n;
    while (~scanf("%d", &n)) {
        for (int i = 1; i <= n; i++)
            scanf("%lld", &a[i]);

        ll ans = 0;
        for (int i = 1; i <= n; i++) {
            ll res = 1;
            for (int j = 1; j <= n; j++) {
                if (i == j)
                    continue;
                res *= (a[j] * a[j] % mod - a[i] * a[i] % mod);
                res %= mod;
            }
            ans += qpow(2 * a[i] % mod * res % mod, mod - 2);
        }
        ans = (ans % mod + mod) % mod;
        cout << ans << endl;
    }
}

E题:ABBA

 题意:有n个"AB",m个"BA",问能结合成多少个序列.这个要求是AB和BA的顺序不变,即A和B的相对位置不变,BA中可以穿插AB,反之亦然

那么我们采用dp,dp[i][j]表示放置i个A和j个B方案数
也就是说我们当前串也就是后面添加A还是添加B的情况

dp[i][j] += dp[i - 1][j];
dp[i][j] += dp[i][j - 1];

 当i ≤ n时,A可以随便放;
 当j ≤ m时,B可以随便放;
 当i > n,如果放A,AB的数量要小于等于n,i - j是至少有多少个AB, i - j ≤ n;
 当j > m,如果放B,BA的数量要小于等于m,j - i是至少有多少个BA, j - i ≤ m;

if(i - j <= n) d[i][j] += d[i - 1][j];
if(j - i <= m) d[i][j] += d[i][j - 1]];

最终代码如下(PS: 用于数据组过多,memset会卡T,跟缓冲区有关)

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

const int mod = 1e9 + 7;
const int maxn = 2e3 + 10;
int dp[maxn][maxn];

int main(void)
{
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        for (int i = 0; i <= n + m; i++)
            for (int j = 0; j <= m + n; j++)
                dp[i][j] = 0;
        dp[0][0] = 1;

        for (int i = 0; i <= n + m; i++) {
            for (int j = 0; j <= m + n; j++) {
                if (i - j < n)
                    dp[i + 1][j] = (dp[i][j] + dp[i + 1][j]) % mod;
                if (j - i < m)
                    dp[i][j + 1] = (dp[i][j] + dp[i][j + 1]) % mod;
            }
        }
        printf("%d\n", dp[n + m][n + m]);
    }

    return 0;
}

F题:Random Point in Triangle

 题意:求三角形内部一个点连三个顶点形成的最大三角形面积的期望,再乘一个36

 答案是 11/2 倍三角形 ABC 的面积

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

struct point{
    long long x, y;
}a, b, c;

point AB, BC;

int main(void)
{
    while (cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y) {
        AB.x = b.x - a.x;
        AB.y = b.y - a.y;
        BC.x = c.x - b.x;
        BC.y = c.y - b.y;
        printf("%lld\n",abs((AB.x * BC.y - AB.y * BC.x)) * 11);
    }

    return 0;
}

J题 :Fraction Comparision

 题意:判断x/a和y/b的大小,其中1 ≤ x, y ≤ 10<sup>18</sup>, 1 ≤ a, b ≤ 10<sup>9</sup>

签到题,这道题我们直接用的大整数写的,判断x * by * a,没什么好说的

其实出题人是想考察数学方面知识的,官方题解是这样的:

  1. 先把 写成
  2. 先比整数部分,分数部分分子分母都在 10<sup>9</sup> 范围内,交叉相乘比较

于是乎,上一下官方题解:

#include <bits/stdc++.h>

static std::pair<uint64_t, uint64_t> fcompare(uint64_t x, uint32_t a, uint64_t y, uint32_t b) {
    uint64_t p = x / a; // p <= (x / a) < p + 1
    uint64_t q = y / b; // q <= (y / b) < q + 1
    if (p != q) {
        return {p, q};
    }
    x %= a;
    y %= b;
    return {x * b, y * a};
}

int main(void)
{
    std::ios::sync_with_stdio(false);
    uint64_t x, y;
    uint32_t a, b;
    while (std::cin >> x >> a >> y >> b) {
        auto result = fcompare(x, a, y, b);
    if (result.first == result.second)
        puts("=");
    else if (result.first < result.second)
        puts("<");
    else
        puts(">");
    }
    return 0;
}
全部评论

相关推荐

点赞 评论 收藏
分享
10-17 12:16
同济大学 Java
7182oat:快快放弃了然后发给我,然后让我也泡他七天最后再拒掉,狠狠羞辱他一把😋
点赞 评论 收藏
分享
我即大橘:耐泡王
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务