科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛)

比赛网址传送门

A 点对最大值

求这个树的直径,已经见过三次了,还是没打出来,注意个别地方稍微修改一下。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {
    
    0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
struct Edge
{
    
    
    int before, to, w;
} e[maxn << 1];
int val[maxn], dp[maxn];
int n, k, head[maxn];
int ans = 0;
void add(int u, int v, int w)
{
    
    
    e[k].before = head[u];
    e[k].to = v;
    e[k].w = w;
    head[u] = k++;
}
void DFS(int u, int fa)
{
    
    
    dp[u] = val[u];
    for (int i = head[u]; i != -1; i = e[i].before)
    {
    
    
        int v = e[i].to;
        if (v == fa)
            continue;
        DFS(v, u);
        ans = max(ans, dp[u] + dp[v] + e[i].w);
        dp[u] = max(dp[u], dp[v] + e[i].w);
    }
}
int main()
{
    
    
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    IO;
    int T;
    scanf("%d", &T);
    while (T--)
    {
    
    
        k = 0;
        memset(head, -1, sizeof head);
        scanf("%d", &n);
        int x, y;
        for (int i = 2; i <= n; i++)
        {
    
    
            scanf("%d %d", &x, &y);
            add(x, i, y);
            add(i, x, y);
        }
        for (int i = 1; i <= n; i++)
            scanf("%d", &val[i]);
        ans = -inf;
        DFS(1, 0);
        cout << ans << "\n";
    }
    return 0;
}

B 减成一

容易发现答案为每一个递增序列的递增差之和,可以把数组当做很多个递增序列(样例为3个递增序列为别递增 (2+2)+5+0=9),但是可能会出现第一个序列即为递减的情况,这时我们可以再在a[0] 位置设置一个1。这样就不需要特判了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
int dis[8][2] = {
    
    0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
LL a[maxn];
int main()
{
    
    
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    // IO;
    int T;
    int n;
    scanf("%d", &T);
    while (T--)
    {
    
    
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%lld", &a[i]);
        a[0] = 1;
        LL ans = 0;
 
        for (int i = 1; i <= n; i++)
        {
    
    
            if (a[i] >= a[i - 1])
                ans += 1LL * a[i] - a[i - 1];
        }
        cout << ans << endl;
    }
    return 0;
}

C 面积

D 扔硬币

这是一个基于二项分布情况下的简单的条件概率,把相对应的概率算出来就好。对于逆元要用线性递推进行预处理,否则T飞。哦对了,组合数也用了递推式,并没有逐个计算。
在这里插入图片描述
但是对于这道题目,只需要处理组合数就行,后面硬币概率算了就多此一举了,可惜我当时还是稀里糊涂得计算了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {
    
    0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
LL c[maxn];
LL inv[maxn];
LL qpow(LL a, LL b, LL c)
{
    
    
    LL ans = 1;
    while (b)
    {
    
    
        if (b & 1)
            ans = ans * a % c;
        a = a * a % c;
        b = b >> 1;
    }
    return ans;
}
LL Inv(LL a, LL p)
{
    
    
    return qpow(a, p - 2, p);
}
int main()
{
    
    
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    // IO;
    int T;
    inv[1] = 1;
    for (int i = 2; i <= maxn; i++)
    {
    
    
        inv[i] = mod - mod / i * inv[mod % i] % mod;
    }
    cin >> T;
    while (T--)
    {
    
    
        LL n, m, k;
        cin >> n >> m >> k;
        if (k > n - m)
        {
    
    
            cout << 0 << endl;
            continue;
        }
        m = n - m;
        LL t1 = qpow(Inv(2, mod), n, mod); // 2 的 n次方
        LL t2 = Inv(k, mod);               //  k 的 逆元
        c[0] = 1;
        LL ans2 = c[0] * t1 % mod;
        for (int i = 1; i <= m; i++)
        {
    
    
            c[i] = ((c[i - 1] % mod * (n - i + 1) % mod) * inv[i] % mod) % mod;
            ans2 = (ans2 % mod + c[i] * t1 % mod) % mod;
        }
        LL ans1 = c[k] * t1 % mod;
        cout << ans1 * Inv(ans2, mod) % mod << endl;
    }
    return 0;
}

E 赛马

O(n^)暴力即可,不要忘了标记。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
int dis[8][2] = {
    
    0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
bool vis[maxn];
int a[maxn], b[maxn];
int main()
{
    
    
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    // IO;
    int T;
    int n;
    cin >> T;
    while (T--)
    {
    
    
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
    
    
            vis[i] = false;
            scanf("%d", &a[i]);
        }
        for (int i = 1; i <= n; i++)
            scanf("%d", &b[i]); // 对手
        sort(a + 1, a + n + 1);
        int ans = 0;
        for (int i = 1; i <= n; i++)
        {
    
    
            int t = b[i];
            int flag = false;
            for (int j = 1; j <= n; j++)
            {
    
    
                if (a[j] > t && vis[j] == false)
                {
    
    
                    flag = true;
                    vis[j] = true;
                    break;
                }
            }
            if (flag)
                ans++;
        }
        cout << ans << endl;
    }
    return 0;
}

F 三角形

这题当时懵了,这么多人做出来,就该再仔细思考一下的。
斐波那契数列对于这题是最完美的,假如给定的长度不满足斐波那契前n项和,那么直接加到最后一条边上,具体看代码。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {
    
    0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
ULL f[200];
 
int main()
{
    
    
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    // IO;
    f[1] = 1;
    f[2] = 1;
    for (int i = 3; i <= 200; i++)
    {
    
    
        f[i] = f[i - 1] + f[i - 2];
        if (f[i] < f[i - 1])
            break;
    }
    int T;
    ULL a;
    cin >> T;
    while (T--)
    {
    
    
        cin >> a;
        for (int i = 1; i <= 93; i++)
        {
    
    
            if (a > f[i])
                a -= f[i];
            else if (a == f[i])
            {
    
    
                cout << i << endl;
                break;
            }
            else if (a < f[i])
            {
    
    
                cout << i - 1 << endl;
                break;
            }
        }
    }
    return 0;
}

G 养花

最大流,建图很多地方不明白,待定。

H 直线

由公式可得答案为 n*(n-1)/2 python水过。。

n = int(input())
for i in range(n):
    m = int(input())
    print(m * (m-1) // 2)

I 字典序

待定。

J 最大值

可以把输入的s当做模式串,s去掉第一个字符做为文本串,进行kmp匹配,维护一个匹配的最大长度,这样就满足题意了,题解说直接求next数组??我还是tcl!!

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 100;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int dis[8][2] = {
    
    0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
string s, p;
int nextp[maxn];
void Get_nextp(int n)
{
    
    
    for (int i = 1; i < n; i++)
    {
    
    
        int j = i;
        while (j > 0)
        {
    
    
            j = nextp[j];
            if (p[i] == p[j])
            {
    
    
                nextp[i + 1] = j + 1;
                break;
            }
        }
    }
}
int Kmp(int n)
{
    
    
    int i, j;
    int ans = -1;
    for (i = 0, j = 0; i < n; i++)
    {
    
    
        if (j < n && s[i] == p[j])
            j++, ans = max(ans, j);
        else
        {
    
    
            while (j > 0)
            {
    
    
                j = nextp[j];
                if (s[i] == p[j])
                {
    
    
                    j++;
                    ans = max(ans, j);
                    break;
                }
            }
        }
    }
    return ans;
}
int main()
{
    
    
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    IO;
    int T, n;
    cin >> T;
    while (T--)
    {
    
    
        cin >> s;
        n = s.size();
        p = s.substr(1, n - 1);
        swap(s, p);
        // cout << s << endl;
        // cout << p << endl;
        Get_nextp(n);
        cout << Kmp(n - 1) << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/106534382