2020牛客寒假算法基础集训营6 D 重排列
https://ac.nowcoder.com/acm/contest/3007/D
题目描述
一个序列的重排列是指对这个序列中的元素进行若干次(包括0次)交换操作后得到的新序列
在本题中,序列中可能出现重复的数字,他们被视作不同的元素
例如,序列1 1的重排列有两种
现在有两个长度为 N 的非负整数序列 A 和 B,问有多少种 A 的重排列满足对于所有的 1≤i≤N,有Ai≤Bi
由于答案可能很大,你只需要输出答案对1e9+7取模的结果
思路
算是一个统计题吧。首先可以明确方案数和 b 序列的顺序无关 ,比如 b 是 1 2 3 4和他是4 3 2 1方案数一样,既然这样就可以换个思路考虑。
因为是让A小于B,所以先把序列B按从小到大排序,接下来考虑,上面对于的
有多少中放的方法,就是上面序列小于等于B[0]的个数,因为小于等于
的一定小于等于
,所以现在
的选择是小于等于自己的个数减去1,以此类推。
因此可以先求小于等于每一个位置的
中的个数,然后循环一遍,每个位置的结果是
,求一个连乘积即可。
#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int n;
ll a[N], b[N];
ll les[N];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)scanf("%lld", a + i);
for (int i = 1; i <= n; i++)scanf("%lld", b + i);
sort(b + 1, b + 1 + n);
sort(a + 1, a + 1 + n);
int l = 1;
les[0] = 0;
for (int i = 1; i <= n; i++){
les[i] = les[i - 1];
for (; l <= n && a[l] <= b[i]; l++){
les[i]++;
}
}
ll res = les[1] % mod;
for (int i = 2; i <= n; i++){
res *= (les[i] - i + 1);
res %= mod;
}
printf("%lld\n", res);
return 0;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12861937.html

浙公网安备 33010602011771号