2019CCPC-江西省赛【部分题解】

比赛只写出来了F,I,J,K。补题:G,C,H。

HDU - 6572:F - String

签到题

题意:给你一个字符串,让你找出能构成"avin"的概率。

思路:直接记录a,v,i,n出现的概率相乘即可。
坑点:约分

AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 150;
char str[maxn], temp[4] = {'a', 'v', 'i', 'n'};
int num[maxn];
void solve() {
    int n;
    while (~scanf("%d", &n)) {
        scanf("%s", &str);
        memset(num, 0, sizeof(num));
        for (int i = 0; i < n ;++i) {
            num[str[i]]++;
        }
        int cnt = 1;
        for (int i = 0; i < 4; ++i) {
            cnt *= num[temp[i]];
        }
        if (!cnt) {
            puts("0/1");
        } else {
            int x = cnt, y = n * n * n * n;
            for (int i = 2; i <= cnt; ++i) {
                if (x % i == 0 && y % i == 0) {
                    x /= i;
                    y /= i;
                }
            }
            printf("%d/%d\n", x, y);
        }
    }
}
int main() {
    solve();
    return 0;
}
HDU - 6575:I - Budget

签到题

题意:给你一个3位小数的浮点数,所有预算将四舍五入到小数点后2位。例如1.003就是-0.003, 1.008就是0.002,给你n个浮点数,求出所有预算的和。

思路:可以用四舍五入函数保留小数点后两位,然后减去原来的数,但是自己不会,就用了个字符串存储,然后取小数点后三位,进行判断是否四舍五入。
坑点:小数相加减可能会出现-0.00的情况,利用eps处理即可。

AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 150;
char str[maxn], temp[4] = {'a', 'v', 'i', 'n'};
int num[maxn];
void solve() {
    int n;
    while (~scanf("%d", &n)) {
        scanf("%s", &str);
        memset(num, 0, sizeof(num));
        for (int i = 0; i < n ;++i) {
            num[str[i]]++;
        }
        int cnt = 1;
        for (int i = 0; i < 4; ++i) {
            cnt *= num[temp[i]];
        }
        if (!cnt) {
            puts("0/1");
        } else {
            int x = cnt, y = n * n * n * n;
            for (int i = 2; i <= cnt; ++i) {
                if (x % i == 0 && y % i == 0) {
                    x /= i;
                    y /= i;
                }
            }
            printf("%d/%d\n", x, y);
        }
    }
}
int main() {
    solve();
    return 0;
}
HDU - 6576:J - Worker

简单数论

题意:有n个仓库和m个工人。在i仓库的任何工人每天都可以处理a[i]订单。客户想知道是否有一种工人分配方法可以满足每个仓库每天处理相同数量的订单.

思路:算出n个仓库每天处理订单的最小公倍数。求出最小公倍数,这个最小公倍数可能是我们每个仓库要完成的订单量,然后求出每个仓库还需要分配多少个(b[i])工人的总和sum,看是否是m的倍数,如果不是,那么肯定不能分配,如果是,则肯定能分配,前面可能的含义:就是每个仓库分m/sum倍的b[i]个工人。这样才能使得m个分配完。
坑点:m的数据范围是1e18,题面表达不清楚。

AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1500;
int a[maxn];
void solve() {
    int n;
    ll m;
    while (~scanf("%d%lld", &n, &m)) {
        scanf("%d", &a[1]);
        int t = a[1] / __gcd(1, a[1]);
        for (int i = 2; i <= n; ++i) {
            scanf("%d", &a[i]);
            t = t * a[i] / __gcd(t, a[i]);
        }
        ll sum = 0;
        for (int i = 1; i <= n; ++i) {
            sum += t / a[i];
        }
        if (sum > m || m % sum) {
            puts("No");
            continue;
        }
        ll ans = t * m / sum;
        puts("Yes");
        for (int i = 1; i <= n; ++i) {
            if (i < n) {
                printf("%lld ", ans / a[i]);
            } else {
                printf("%lld\n", ans / a[i]);
            }
        }
    }
}
int main() {
    solve();
    return 0;
}
HDU - 6577:K - Class

签到题
两个式子联立解方程即可。

AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;

void solve() {
    int x, y;
    scanf("%d%d", &x, &y);
    printf("%d\n", (x * x - y * y) / 4);
}
int main() {

    solve();
    return 0;
}
HDU - 6573:G - Traffic

签到题

题意:你要在交叉路口拍照,然后有东西方向行驶的车和南北方向行驶的车,为了避免发生碰撞,南北方向的车会等待相同的时间。

思路:暴力枚举等多长时间,南北方向的所有车都能通过且不与东西方向的车相撞。

AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2500;
int b[maxn], num[maxn];
void solve() {
    int n, m, x;
    while (~scanf("%d%d", &n, &m)) {
        memset(num, 0, sizeof(num));
        for (int i = 0; i < n; ++i) {
            scanf("%d", &x);
            num[x]++;
        }
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &b[i]);
        }
        int f = 0;
        for (int i = 0; ; ++i) {
            f = 0;
            for (int j = 1; j <= m; ++j) {
                if (num[b[j] + i] == 1) {
                    f = 1;
                    break;
                }
            }
            if (!f) {
                printf("%d\n", i);
                break;
            }
        }
    }
}
int main() {
    solve();
    return 0;
}
HDU - 6570:C - Wave

简单DP

题意:给出n个数字,找一个类似于abab…形式的子序列,求其最长的长度。

思路:dp(i,j)表示当前数字为j,前一个数字为i的序列长度。

AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2500;
int dp[105][105];
void solve() {
    int n, c, x;
    while (~scanf("%d%d", &n, &c)) {
        memset(dp, 0, sizeof(dp));
        int ans = 0;
        while (n--) {
            scanf("%d", &x);
            for (int i = 1; i <= c; ++i) {
                dp[i][x] = dp[x][i] + 1;
                if (i != x) {
                    ans = max(ans, dp[i][x]);
                }
            }
        }
        printf("%d\n", ans);
    }
}
int main() {
    solve();
    return 0;
}
HDU - 6574:H - Rng

逆元+数学

题意:给定一个n,然后让你随机生成两个区间,随机生成一个r∈[1,n],在随机生成一个l∈[1,r],求两个区间相交的概率q/p % 1e9 + 7.

思路:随机生成一个r的概率为1/n,随机生成一个l的概率为1/(n - i + 1);
判断相交很难,可以用对立事件,1-两个区间不相交,下面来看怎么处理不相交。
在这里插入图片描述
我们让第一段区间的右端点小于第二段的左端点,这样第一段的左端点和第二段的右端点可以取值如下图, 第一段可以取值i,第二段可以取值n - i - 1.
在这里插入图片描述
枚举从1到n枚举i,这样个i边界就为n - 1,所以总和就为n * (n - 1),真的是这样吗?其实不然,当i到中间位置是,前面的两个区间就枚举过了,所以要除以2,不相交的概率为n * (n - 1) / 2 / (n * n), 相交的概率用1减去化简得,(n + 1) / (2 * n), 最后用逆元来处理即可。

AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll fast_power(ll a, ll b) {
    ll ans = 1;
    while(b > 0) {
        if (b & 1) ans = ans * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return ans % mod;
}
void solve() {
    ll n;
    while (~scanf("%lld", &n)) {
        printf("%lld\n", (n + 1) * fast_power(2 * n, mod - 2) % mod);
    }
}
int main() {
    solve();
    return 0;
}

目前尚未有2024年CCPC辽宁区的具体题目解析或题解公开发布,因为该事通常会在每年的下半年举行,而相关题解和官方解析一般会在比结束后的一段时间内由参队伍、教练或者社区整理分享。以下是基于过往CCPC事的经验以及类似的编程竞题型总结的内容框架,供参考。 ### 可能涉及的主要题型及解决方案 #### 数据结构与算法优化 在CCPC中,数据结构的应用非常广泛,尤其是树状数组、线段树等高效的数据结构。例如,在解决区间查询问题时,可以采用如下方法实现高效的前缀和计算: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 10; long long tree[MAXN]; void update(int idx, int val, int n) { while (idx <= n) { tree[idx] += val; idx += idx & (-idx); } } long long query(int idx) { long long sum = 0; while (idx > 0) { sum += tree[idx]; idx -= idx & (-idx); } return sum; } ``` 此代码片段展示了如何利用树状数组来快速完成单点修改和区间查询的操作[^1]。 #### 图论问题 图论问题是CCPC中的常见考点之一,特别是最短路径、最小生成树等问题。Dijkstra算法是一种经典的求解单一源节点到其他所有节点最短距离的方法: ```cpp #include <bits/stdc++.h> using namespace std; struct Edge { int to, cost; }; vector<Edge> G[10001]; bool used[10001]; long long d[10001]; void dijkstra(int s) { priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> que; fill(d, d + 10001, LLONG_MAX); d[s] = 0; que.push({0, s}); while (!que.empty()) { pair<long long, int> p = que.top(); que.pop(); int v = p.second; if(used[v]) continue; used[v] = true; for(auto e : G[v]){ if(!used[e.to] && d[e.to] > d[v] + e.cost){ d[e.to] = d[v] + e.cost; que.push({d[e.to], e.to}); } } } } ``` 上述代码实现了带权重图上的单源最短路径寻找过程[^3]。 #### 动态规划 动态规划也是竞中不可或缺的一部分,尤其适用于具有重叠子问题特性的场景。比如背包问题可以通过以下方式解决: ```cpp #include <bits/stdc++.h> using namespace std; int dp[1001][1001]; int knapsack(int W, int wt[], int val[], int n) { for (int i = 0; i <= n; i++) { for (int w = 0; w <= W; w++) { if (i == 0 || w == 0) dp[i][w] = 0; else if (wt[i - 1] <= w) dp[i][w] = max(val[i - 1] + dp[i - 1][w - wt[i - 1]], dp[i - 1][w]); else dp[i][w] = dp[i - 1][w]; } } return dp[n][W]; } ``` 这里提供了一个标准的0-1背包问题解决方案[^4]。 ### 结语 尽管当前无法获取具体的2024 CCPC辽宁题解,但从以往的比来看,重点仍然集中在基础算法的理解应用及其变种形式上。建议持续关注各大高校ACM/ICPC团队博客、OJ平台后讨论区以及相关社交媒体群组,以便及时获得最新资讯。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值