Comet OJ 分配学号 map

Posted ydw--

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Comet OJ 分配学号 map相关的知识,希望对你有一定的参考价值。

题目描述

 

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

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

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

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

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

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

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

 

 
 

输入描述

 

第一行包含一个正整数 n,代表学生的数量(1n105)

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

 

输出描述

 

输出一个整数表示最终学号的方案数。(答案对 10^9+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 1 2   要变成1 2 2 2(三个2中选2个变2)现在2多了(1的个数-1)个 所以就从3个中选2个变成3    -> 1 2 3 3  在两个3中选1个变4

so  就是概率题  即n个中选(n-1)个即n中选1   所以答案就是3*3*2;

代码:

技术图片
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mod=1e9+7;
map<ll,ll>mm;
int main()

    ll x,n;
    cin>>n;
    for (int i = 0; i < n; i++)
        scanf("%lld", &x),mm[x]++;
    ll ans=1;
    map<ll,ll>::iterator it;
    for(it=mm.begin();it!=mm.end();it++)//要用map 否则用数组什么的 范围10^18 for会超时啊     迭代器遍历 只有mm【x】有值才会遍历到 so 不会超时噢
    
        ll yy=it->second;
        ans=ans*yy%mod;
        if(yy>1)mm[it->first+1]+=(yy-1);
    
    printf("%lld\n", ans);
    return 0;
View Code

 

以上是关于Comet OJ 分配学号 map的主要内容,如果未能解决你的问题,请参考以下文章

Comet OJ Contest #3

Comet OJ Contest #2

Comet OJ - Contest #3

Comet OJ - Contest #12

Comet OJ - Contest #2

Comet OJ - Contest #15题解