牛客周赛 Round 61(思维、组合数)

牛客周赛 Round 61(思维、组合数)


整体不是很难,想明白细节即可。


A. Letter Song ~ 致十年后的我们

注意题意,不考虑闰年,直接Y+10即可。

#include<bits/stdc++.h>

using namespace std;

int main(){
    
    int a, b, c;
    scanf("%d-%d-%d", &a, &b, &c);
    
    printf("%d-%02d-%02d\n", a+10, b, c);
    
    return 0;
}

B. 简单图形问题 - 0123

显然,边长是整数的等边三角形,面积不可能为整数。只需要判断是否为正方形即可。

#include<bits/stdc++.h>

using namespace std;

int main(){
    
    int ncase;
    cin >> ncase;
    
    while(ncase--){
        long long n;
        cin >> n;
        long long a = sqrt(n);
        if(a * a == n) cout << 0 << endl;
        else cout << 3 << endl;
    }
    
    return 0;
}

C. 小红的机器人构造 - Ⅰ+Ⅱ+Ⅲ(思维,组合数)

  1. 对于UD 和 LR是两个相对独立的维度,互不影响,可以分开考虑。
  2. 对于是否能达到目标点,用 x 轴方向举例:
    • X < 0 时,一个指令D 可以让 X - 1,判断 D 的个数是否大于等于 |X| 即可
    • X > 0 时,一个指令U 可以让 X + 1, 判断 U 的个数是否大于等于 |X| 即可
    • 同理,判断 y轴是否满足。如果 x 和 y 同时满足,则为YES。
  3. 对于YES的情况,考虑方案数,用 x 轴方向举例:
    • C X C_X CX 表示指令X必须保留的个数。
    • X < 0 时,说明必须保留 |X| 个指令 D,此时 C D = ∣ X ∣ C_D = |X| CD=X C U = 0 C_U = 0 CU=0
    • X > 0 时,说明必须保留 |X| 个指令 U,此时 C U = ∣ X ∣ C_U = |X| CU=X C D = 0 C_D = 0 CD=0
    • 除必须要保留的指令外,剩下的指令 U 和指令 D 需要考虑删除。
    • 设$V(X) = $ 指令 X 的个数 , c n t ( X ) = V ( X ) − C X cnt(X) = V(X) - C_X cnt(X)=V(X)CX ,即 c n t ( X ) cnt(X) cnt(X) 表示指令X最多要删除的个数。
    • 显然,多保留一个指令 U,就需要多保留一个指令 D。枚举每一种多保留指令的情况,即可。
    • c n t ( U ) > c n t ( D ) cnt(U) > cnt(D) cnt(U)>cnt(D) c u r = c n t ( U ) − c n t ( D ) cur = cnt(U) - cnt(D) cur=cnt(U)cnt(D),其中 c u r cur cur 就表示 U 必须要删除的指令个数,其他的均可以选择保留一对UD or 删除
    • 在这种情况下,在 x 轴方向上,贡献的方案数为: ∑ 0 c n t ( D ) C [ V ( D ) , i ] ∗ C [ V ( U ) , i + c u r ] \sum_0^{cnt(D)}C[V(D), i] * C[V(U), i+cur] 0cnt(D)C[V(D),i]C[V(U),i+cur],其中 C [ X , Y ] C[X, Y] C[X,Y] 表示在 X 中选择 Y 个组合数。
    • c n t ( D ) > c n t ( U ) cnt(D) > cnt(U) cnt(D)>cnt(U) 时,贡献的方案同时。
    • 在 y 轴方向上,贡献的方案同上。
    • 最终答案 = x 轴方向贡献的方案 * y 轴方向贡献的方案。
#include<bits/stdc++.h>
#define ll long long
using namespace std;

const ll mod = 1e9 + 7;
const int maxn = 1e6 + 5;
const string op = "UDRL";

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;
}

ll f[maxn], p[maxn];
ll C(ll a, ll b){	// 计算C(a,b)
    return f[a] * p[b] % mod * p[a-b] % mod;
}

int main(){

    f[0] = 1;
    for(int i = 1; i < maxn; i++) f[i] = f[i-1] * i % mod;
    for(int i = 0; i < maxn; i++) p[i] = qpow(f[i], mod-2); // 费马小定理求逆元
    int ncase;
    cin >> ncase;
    
    while(ncase--){
        int n, x, y;
        cin >> n >> x >> y;
        string s, ss;
        cin >> s;
        ll u = 0, d = 0, l = 0, r = 0;
        map<char, ll> v;
        for(auto c : s){
        	if(c == 'U' && x > 0) x--, ss = ss + c; 
        	else if(c == 'U') u++;
        	else if(c == 'D' && x < 0) x++, ss = ss + c; 
        	else if(c == 'D') d++;
        	else if(c == 'L' && y < 0) y++, ss = ss + c; 
        	else if(c == 'L') l++;
        	else if(c == 'R' && y > 0) y--, ss = ss + c; 
        	else r++;
        	v[c]++;
		}
		if(x != 0 || y != 0) cout << "NO" << endl; // 判断是否可以走到终点
		else{
			cout << "YES " << ss << " "; // 当前的ss是最小串,即udlr是最多删除 
			ll cnt1 = 0, cnt2 = 0;
			if(u < d) swap(u, d), swap(v['U'], v['D']); // D > U时,交换即可,对于计算方案数
			ll cur = u - d;
			for(ll i = 0; i <= d; i++){
				ll tmp = C(v['U'], i+cur) * C(v['D'], i) % mod;
				cnt1 = (cnt1 + tmp) % mod;
			}
			if(l < r) swap(l, r), swap(v['L'], v['R']); // 同上
			cur = l - r;
			for(int i = 0; i <= r; i++){
				ll tmp = C(v['L'], i+cur) * C(v['R'], i) % mod;
				cnt2 = (cnt2 + tmp) % mod;
			}
			ll res = cnt1 * cnt2 % mod;
			cout << res << endl;
		} 
    }
    
    return 0;
}

D. 小红的差值构造 - easy+hard+extreme (思维)

看极限版本的数据范围,显然是结论题。

对于 l > n 的情况,显然把 y 或 x 落在 n 的中间是最佳的。

对于 l < n 的情况,把 l+1 这个区间和 n 这个区间的中间重叠时为最佳。

对于上述两种情况,可以选择几组(n,l),手动移动一下重叠区间即可,注意考虑奇偶。

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

int main(){
    
    int ncase;
    cin >> ncase;
    
    while(ncase--){
        ll n, l;
        cin >> n >> l;
        l++;
        if(l > n){
        	ll x = (n+1) / 2;
        	cout << x - l + 1 << " " << x << " " << x * (x-1) + ((n&1) ? 0 : x) << endl;
        }
        else{
            ll x = (n - l) / 2;
            ll res = (x+1) * x + ((n-l) & 1 ? x+1 : 0);
            ll t = (l - 2) / 2;
            res = res + (t+1) * t + ((l-2) & 1 ? t+1 : 0);
            cout << n/2-t+1 << " " << n/2-t+1 + l - 1 << " " << res << endl;
        }
    }
    
    return 0;
}   
关于Round 83 的具体题目和解答,目前并未提供直接的引用支持。然而,可以基于以往的经验以及类似的周赛模式来推测可能涉及的内容结构。 通常情况下,周赛会包含多个不同难度级别的题目,从简单的签到题(A 类型)到较难的挑战性问题(E 或 F 类型)。以下是根据已有经验构建的一般框架: ### 周赛 Round 83 可能的主题 #### A - 签到题 这类题目通常是简单算法的应用或者基础逻辑判断。例如: ```python def solve_a(): n = int(input()) result = sum(range(1, n + 1)) # 计算前N项自然数之和 print(result) solve_a() ``` 此部分无需深入解析,主要考察参赛者的基础编程能力[^1]。 #### B - 中等难度题 此类题目可能会涉及到数组操作、字符串处理或基本数据结构应用。比如给定一段文字统计特定字符频率的问题。 ```python from collections import Counter def solve_b(): s = input().strip() counter = Counter(s) most_common_char, count = counter.most_common(1)[0] print(most_common_char, count) solve_b() ``` 上述代码片段展示了如何利用Python内置库快速解决常见计数类问题[^2]。 #### C/D/E/F 更高阶挑战 这些更复杂的任务往往需要运用高级技巧如动态规划(DP),图论(Graph Theory)或者其他专门领域知识才能有效完成。由于缺乏具体的Round 83资料,这里仅给出一个假设性的例子有关最短路径寻找: ```python import heapq INF = float('inf') def dijkstra(graph, start_node): distances = {node: INF for node in graph} distances[start_node] = 0 priority_queue = [(0, start_node)] while priority_queue: current_distance, current_vertex = heapq.heappop(priority_queue) if current_distance > distances[current_vertex]: continue for neighbor, weight in graph[current_vertex].items(): distance = current_distance + weight if distance < distances[neighbor]: distances[neighbor] = distance heapq.heappush(priority_queue, (distance, neighbor)) return distances graph_example = { 'A': {'B': 1, 'C': 4}, 'B': {'A': 1, 'C': 2, 'D': 5}, 'C': {'A': 4, 'B': 2, 'D': 1}, 'D': {'B': 5, 'C': 1} } print(dijkstra(graph_example, 'A')) ``` 这段程序实现了经典的迪杰斯特拉算法用于求解加权无向图中的单源最短路径问题[^3]. 尽管无法确切知道每道实际考题是什么样子,但通过以上介绍应该能够帮助理解一般竞赛形式下的潜在考点及其解决方案设计方法.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值