• P1866 编号 题解


    题目描述

    太郎有N只兔子,现在为了方便识别它们,太郎要给他们编号。兔子们向太郎表达了它们对号码的喜好,每个兔子i想要一个整数,介于1和Maxnumber[i]之间(包括1和Maxnumber[i])。当然,每个兔子的编号是不同的。现在太郎想知道一共有多少种编号的方法。

    你只用输出答案mod 1000000007即可。如果这是不可能的,就输出0.

    输入格式

    第一行是一个整数N。(1≤N≤50)

    第二行N个整数Maxnumber[i]。(1≤Maxnumber[i]≤1000)

    输出格式

    一个整数

    输入输出样例

    输入 #1
    2
    5 8
    
    输出 #1
    35

    题目分析

    通过乘法原理,可知

    若某个对象分为n个环节,第1个环节有m1个元素,第2个环节有m2个元素,……,第n个环节有mn个元素,则该对象有 N=m1×m2×m3×…×mn 种序列。
    将此结论代入题目,可得:

    若Maxnumber数组已被从小到大排序(排序方法很多,这里用桶排序),则:ans分为N个环节,第1个环节有Maxnumber[0]-0个元素,第2个环节有Maxnumber[1]-1个元素,……,第N个环节有Maxnumber[N-1]-(N-1)个元素,则ans有 (Maxnumber[0]-0)*(Maxnumber[1]-1)*…(Maxnumber[N-1]-(N-1))种序列。

    (因为第2个环节可选元素必与第1个环节选到的元素重复,要减1;第3个环节可选元素必与第1个环节选到的元素,第2个环节选到的元素重复,要减2…第N个环节可选元素必与第1个环节选到的元素,第2个环节选到的元素,…,第(N-1)个环节选到的元素重复,要减(N-1)。 )

    上代码:

    #include<iostream>
    using namespace std;
    int main(){
    long long N,a,ans=1,Maxnumber[1001]={0},s=0;
    cin>>N;
    for(int i=0;i<N;i++){
    cin>>a;
    Maxnumber[a]++;
    }//桶排序
    for(int i=0;i<1001;i++){
    if(Maxnumber[i]){/*等价于if(Maxnumber[i]!=0)*/
    if(i-s<=0){
    cout<<0;
    return 0;
    //不符合由乘法原理得出的结论,不可能实现。输出"0",结束程序
    }
    else{
    while(Maxnumber[i]!=0){
    ans=(ans*(i-s))%1000000007;
    s++;
    Maxnumber[i]--;
    }
    }
    if(s==N){
    break;
    //所有元素已遍历,跳出循环
    }
    }
    }
    cout<<ans;
    return 0;
    }

  • 相关阅读:
    Android xml text 预览属性
    GridView、ListView默认的点击背景修改
    java.util.ConcurrentModificationException
    Android 菜单定制使用小结
    Panel 中加载窗体
    git代理配置
    TableLayoutPanel 动态添加 行 列
    C# 左右补零
    Dart Map<> 添加 元素
    Mac 永久添加 环境变量方法
  • 原文地址:https://www.cnblogs.com/samuelx/p/12849953.html
Copyright © 2020-2023  润新知