CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)H——分配学号(思维+组合数学)

本文探讨了一个关于分配学号的算法问题,旨在确保每位学生获得唯一且满足特定条件的学号。通过分析和理解题目的核心需求,文章提出了有效的解决方案,包括如何在保持学号递增的前提下,最小化学号调整的总变动量。通过分块和组合数学的方法,文章给出了具体的实现思路和代码示例。

分配学号

已经提交 已经通过 时间限制:1000ms 内存限制:256MB

84.41%

提交人数:186

通过人数:157

题目描述

 

今天,是JWJU给同学们分配学号的一天!为了让大家尽可能的得到自己想要的学号,鸡尾酒让大家先从 [1,10^{18}][1,1018] 中随机挑选一个数字作为自己的学号。但是总有一些心有灵犀的小伙伴们选择了一样的数字——显然这样是不合法的,因为每个人的学号都应该是唯一的。

于是鸡尾酒决定调整大家的学号。他采用如下两个原则来修改:

1、只增不减,每个人的最终学号 ≥ 每个人初始选择的学号

2、总修改量尽量少,总修改量指每一个人的改动量之和。(改动量即为最终学号减初始学号的值)

注意,修改后的最终学号可以大于10^{18}1018。

很显然,如果现在有两个同学 A 和 B,初始选择的学号均为1号,他们有可能被鸡尾酒改动成 A 同学为 11 号和 B 同学为 22 号,或者改动成 B 同学为 11 号和 A 同学为 22 号。

鸡尾酒邪魅一笑,他想让你告诉他,大家的最终学号共有多少种不同的分配方案。

输入描述

 

第一行包含一个正整数 nn,代表学生的数量。(1 \le n \le 10^{5})(1≤n≤105)

接下来一行包含 nn 个正整数,分别代表每个学生的初始选择的学号。(取值范围[1,10^{18}])[1,1018])

输出描述

 

输出一个整数表示最终学号的方案数。(答案对 10^{9}+7109+7 取模)

在两个最终学号的分配方案中,若存在某一个学生在两个方案中的学号不相同,则认为是这两个方案是不同的分配方案。

样例输入 1 

3
1 1 2

样例输出 1

4

样例输入 2 

2
1 5

样例输出 2

1

提示

对于第一组样例,最终的学号分配方案有以下4种:

[1,2,3], [1,3,2], [2,1,3], [3,1,2][1,2,3],[1,3,2],[2,1,3],[3,1,2]

分配之后每个学生的学号均不相同,且这几种方案的总修改量都是最小的。

 

对于第二组样例,每个学生的学号已经都不相同,所以无需修改,所以最终分配方案只有11种,即[1,5][1,5]。

题意:不解释

题解:首先想满足两个条件,第一个简单,增加就好,主要是第二个,怎么办,我们可以分块来写,然后对块内进行组合数学分步乘法,当然要先排序~~

举个例子怎么保证最小:1 1 2 3 7 7      我们分成1 1 2 3       7 7    两块,显然这样对块内处理就能保证总修改最小,分块的条件是  前面的数字个数 < 下一块的第一个数  比如举的例子 1 1 2 3 数字个数4  < 7 这样就进入下一块,否则就是在块内~~详细请看代码哦~~

上代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX = 1e5+6;
const int mod = 1e9+7;
ll a[MAX];
int main(){
	int n;
	scanf("%d",&n);
	for (int i = 0; i < n;i++){
		scanf("%lld",&a[i]);
	}
	sort(a,a+n);
	ll ans=1;
	for (int i = 0,j; i < n; i = j){
		for (j = i+1; j < n&&a[i]+j-i>=a[j];j++){//分块
			ans=(ans*(a[i]+j-i-a[j]+1))%mod;//组合数学分步乘法(块内操作)
		}
	}
	cout << ans << endl;
    return 0;
}

 

### CCPC 2023 H题 解析 关于CCPC 2023 H题的具体题目描述尚未公开,但从以往的比惯例以及类似的题目解析可以推测其可能涉及的内容和技术要点。以下是基于已有参考资料和专业知识对该类问题的解答框架。 #### 1. **问题背景** CCPC(Chinese Collegiate Programming Contest)作为国内重要的编程竞之一,通常会设计具有挑战性的算法问题来测试参者的逻辑思维能力和编码技巧。H题通常是比中的难点之一,往往涉及到复杂的算法模型或数据结构的应用[^2]。 #### 2. **潜在的技术方向** 根据过往的经验,H题可能会覆盖以下几个方面: - 动态规划 (Dynamic Programming)[^1] - 构造性问题 (Construction Problems)[^4] - 数学优化 (Mathematical Optimization) 假设该题属于动态规划类别,则需关注状态转移方程的设计;如果是构造性问题,则重点在于如何通过有限操作达到目标条件。 #### 3. **通用解题策略** 无论具体主题为何种类型,在面对高难度题时可遵循如下方法论: ##### (1)深入理解题目需求 仔细阅读并反复确认输入输出的要求及其约束条件,确保不会遗漏任何细节信息[^3]。 ##### (2)选取合适的算法工具箱 依据实际场景挑选最匹配的方法论,比如当存在重叠子问题且具备最优子结构性质时优先选用DP技术[^1]。 ##### (3)编写清晰易懂的代码实现 采用模块化的方式分步完成整个功能开发流程,并辅以充分注释说明每一部分的作用机制。 ```cpp // 示例伪代码片段展示基本框架布局 #include &lt;bits/stdc++.h&gt; using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); int n; cin &gt;&gt; n; // 输入规模参数 vector&lt;long long&gt; dp(n+1, INF); // 初始化dp数组,默认极大值表示未访问过 dp[0]=0; for(int i=1;i&lt;=n;i++){ for(auto &amp;coin : coins){ if(i &gt;= coin &amp;&amp; dp[i - coin]+costs[coin]&lt;dp[i]){ dp[i]=dp[i - coin]+costs[coin]; } } } cout &lt;&lt; (dp[n]==INF ? -1 : dp[n])&lt;&lt; &quot;\n&quot;; } ``` 上述例子仅作示意用途,真实情况下应严格依照官方给定的数据范围调整变量类型及边界处理方式。 #### 4. **复杂度考量** 对于大规模实例而言,效率至关重要。因此除了正确率之外还需兼顾运行时间和内存消耗指标。一般建议尽可能降低渐近时间开销至O(NlogN)甚至更低级别。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

心脏dance

如果解决了您的疑惑,谢谢打赏呦

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

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

打赏作者

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

抵扣说明:

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

余额充值