阿里淘天2023秋招-讨厌鬼的排列(map)

讨厌鬼有一个长度为n的数组,他想知道这个数组有多少个子序列是一个排列?
子序列的定义:数组删除若干个元素(也可以不删)后得到的新数组。
排列的定义:长度为m的数组,1到m每个元素都出现过,且恰好出现1次。

输入
第一行输入一个整数n (\(1 < n < 10^5\))
第二行输入n个整数\(a_i\) (\(1 < a < 10^9\))

输出
一行一个整数,表示有多少个子序列是一个排列。由于答案过大,请将答案对\(10^9+7\)取模后输出

样例输入
6
1 1 5 2 3 4
样例输出 复制
10
提示
符合要求的子序列有:{1},{1},{1,2},{1,2},{1,2,3},{1,2,3},{1,2,3,4},{1,2,3,4},{1,5,2,3,4},{1,5,2,3,4}共10个

其实仔细考虑一下这个题和顺序没有什么关系的。所以可以之间拍个序。
然后就是哈希表map了,我们定义一个cnt[i]代表i的个数,sum[i]代表[1..i]的个数
举个例子:
1 1 2 2 3 3
1有两个,cnt[1]=2;sum[1]=2,
2有两个,cnt[2]=2,sum[2]=cnt[2] * sum[1]=4,那么[1,2]的排列就是cnt[2] * sum[1],就是2的个数乘前面1的排列的个数
3有两个,cnt[3]=2,sum[3]=cnt[3] * sum[2]=8,也就是3有两个,然后[1,2]的排列有四种,那么[1,2,3]的排列就有8种

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<map>
typedef long long ll;
using namespace std;
const int maxn=1e6+100;
const int mod=1e9+7;
ll a[maxn];
map<int,ll>cnt,sum;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+n+1);
	cnt[0]=1;
	sum[0]=1;
	for(int i=1;i<=n;i++){
		cnt[a[i]]++;
		sum[a[i]]=(cnt[a[i]]*sum[a[i]-1])%mod;
	}
	ll ans=0; 
	for(int i=1;i<=n;i++){
		ans=(ans+sum[i])%mod;
	}
	cout<<ans<<endl;
}
posted @ 2024-04-22 19:51  lipu123  阅读(66)  评论(0)    收藏  举报