Arrange
Accepts: 221
Submissions: 1401
Time Limit: 8000/4000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
Cupid一不小心将爱情之箭射到了自己,他爱上了Psyche。 这引起了他的母亲Venus的注意。Venus将Psyche带到了一堆打乱的谷堆旁。 这儿共有n堆稻谷,编号为1到n。Psyche需要将这些谷堆以某种顺序排列,设最终排在第i位的谷堆是Ai。 她得知了一些该排列的要求: 1. 对于任意整数i∈[1,n],A1,A2,...,Ai的最小值为Bi。 2. 对于任意整数i∈[1,n],A1,A2,...,Ai的最大值为Ci。 现在Psyche想知道,共有多少种合法的排列。由于答案可能很大,输出时对998244353取模。
输入描述
第一行,一个整数T (1≤T≤15),代表数据组数。 对于每组数据,第一行有一个整数n (1≤n≤105),代表排列大小。 第二行,n个整数,第i个整数为Bi (1≤Bi≤n)。 第三行,n个整数,第i个整数为Ci (1≤Ci≤n)。
输出描述
输出T行,对于每组数据输出答案对998244353取模的结果。
输入样例
2 3 2 1 1 2 2 3 5 5 4 3 2 1 1 2 3 4 5
输出样例
1 0
Hint
对于第一组数据,只有一种合法的排列(2,1,3)。
对于第二组数据,没有合法的排列。
解题思路:
这道题有很多的点需要小心
总体来说,就两个点,一个是判断有无解,一个是计算解的个数
求解解的个数就是直接类似全排列的方式求就行,这个并不难。主要是判断有无解。
无解的情况有:
1.b[0]和c[0]不相等
2.b[i]比c[i]大
3.b序列不是单调非升序
4.c序列不是单调非降序
5.在第i个位置时没有可以放在这个位置的元素
代码如下:
#include <cstdio> #include <cstring> using namespace std; #define mod 998244353 #define INF 0x3f3f3f3f typedef long long LL; const int maxn = 1e5 + 5; int a[maxn], b[maxn]; int main() { // freopen("test.in", "r+", stdin); // freopen("test.out", "w+", stdout); int t, n; scanf("%d", &t); while(t--){ scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i <= n; ++i) scanf("%d", &b[i]); a[0] = INF; b[0] = -1; LL ans = 1; for(int i = 1; i <= n; ++i){ if(i == 1 && a[i] != b[i]){ ans = 0; break; } if(a[i] > a[i-1]) { ans = 0; break; } if(b[i] < b[i-1]){ ans = 0; break; } if(b[i] < a[i]){ ans = 0; break; } if(i != 1 && a[i] < a[i-1] && b[i] > b[i-1]){ ans = 0; break; } if(a[i] == a[i-1] && b[i] == b[i-1]){ if(b[i] - a[i] + 2 - i <= 0) { ans = 0; break; } ans = (ans * (b[i] - a[i] + 2 - i)) % mod; } } printf("%lld ", ans); } return 0; }