首页 > 其他分享 >CF1946E Girl Permutation

CF1946E Girl Permutation

时间:2024-08-18 19:27:11浏览次数:6  
标签:tmp int inv CF1946E m1 Permutation fac Girl mod

中文题面:https://www.luogu.com.cn/problem/CF1946E

先考虑只要求前缀最大值怎么做。从前往后很容易想到\(O(n^3)\)的dp,用前缀和优化可以到\(O(n^2)\).注意相对顺序,\([p_i,p_{i+1}-1]\)选择的数,必须让最大的放在最前面才合法。比如选1,3,9,在[5,8]这个区间,只有9,1,3和9,3,1是合法的。从后往前考虑每一段,发现前面的选择对后面没有影响(相对顺序不变)。

后缀最大值考虑的方法类似。注意判断合法状态。a[m1] != b[1] || a[1] != 1 || b[m2] != n, 即最大值在前后缀相同,前缀第一个在1,后缀最后一个在n。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 1e9 + 7;
const int N = 2e5 + 11;
int a[N], b[N];
int n, m1, m2;
LL fac[N], invo[N], inv[N];
LL C(int n, int m){
  return fac[n] * inv[m] % mod * inv[n-m] % mod;
}
void work(){
  cin>>n>>m1>>m2;
  for(int i = 1;i <= m1; i++){
    scanf("%d", &a[i]);
  }
  for(int i = 1;i <= m2; i++){
    scanf("%d", &b[i]);
  }
  if(a[m1] != b[1] || a[1] != 1 || b[m2] != n){
    cout<<0<<endl;
    return ;
  }
  LL res = C(n - 1, a[m1] - 1);
  LL tmp = a[m1] - 1;
  for(int i = m1 - 1;i >= 1; i--){
    tmp--;
    res = res * C(tmp, a[i+1] - a[i] - 1) % mod * fac[a[i+1]-a[i]-1] % mod;
    tmp -= a[i+1] - a[i] - 1;
  }
  tmp = n - a[m1];
  for(int i = 1;i < m2; i++){
    tmp--;
    res = res * C(tmp, b[i+1] - b[i] - 1) % mod * fac[b[i+1]-b[i]-1] % mod;
    tmp -= b[i+1] - b[i] - 1;
  }
  cout<<res<<endl;
}
int main(){
  int T;
  cin>>T;
  fac[0] = fac[1] = inv[0] = inv[1] = 1;
  for(int i = 1;i <= 2e5; i++){
    fac[i] = 1ll * fac[i-1] * i % mod;
  }
  for(int i = 2;i <= 2e5; i++){
    inv[i] = (mod - mod / i) * inv[mod%i] % mod;
  }
  for(int i = 2;i <= 2e5; i++){
    invo[i] = inv[i];
    inv[i] = inv[i-1] * inv[i] % mod;
  }
  while(T--)work();
  return 0;
}

标签:tmp,int,inv,CF1946E,m1,Permutation,fac,Girl,mod
From: https://www.cnblogs.com/dqk2003/p/18365963

相关文章

  • next_permutation
    使用next_permutation函数非常简单,以下是具体的步骤和注意事项:步骤:包含头文件:确保包含<algorithm>头文件,因为next_permutation函数位于这个头文件中。#include<algorithm>准备容器:next_permutation可以用于处理任何支持随机访问迭代器的容器,比如vector或strin......
  • permutation 不仅仅排列,组合也可以
    排序:1——n所有不重复的排列include<bits/stdc++.h>usingnamespacestd;inta[10];intmain(){intn,i,j=1,k;cin>>n;for(i=1;i<=n;i++){a[i]=i;//a[1~n]=1——n}do{for(k=1;k<=n;k++)printf("%5d",a[k]);printf("\n");}whi......
  • Manhattan Permutations
    首先观察样例,不难发现有可能\(k\)为奇的时候无解证明:《离散数学》中有一道题目的trick是\(|i-j|\)与\(i+j\)的奇偶性相同,所以曼哈顿排列的奇偶性与\(p_1+1+p_2+2+...+p_n+n=2(1+2+3+...+n)\),后者显然为偶数,所以\(k\)为奇时无解其次一个很自然的想法就是当\(p\)为\([n,n-1,n-2,........
  • Splittable Permutations
    第一次自己独立做出来的*2500,纪念一下首先模拟样例不难发现我们可以确定在\(l,r\)中出现过的数字(称这些数为“固定数”)的相对顺序(比如第一个样例,相对顺序为6425,我们只用插入\(1\)和\(3\)就好了),用链表维护就好了考虑剩下的某个数\(x\),不难发现它能放在的地方必须要求与其相邻......
  • CF1768D Lucky Permutation Solution
    CF1768D题意不再简述。首先题目要求变成逆序对只有一个的排列,也就是说,我们可以先考虑将一个排列通过交换元素变成另一个排列最小的步数,我们可以将两个排列相同位置上的数连边,很显然会形成几个环,若排列长度为\(n\),形成\(t\)个环,每个环长为\(len_i\),则每个环交换完至少是依次......
  • Solution - Atcoder ARC114F Permutation Division
    令\(a\)为题目中的\(P\)。首先考虑后手的重排策略是什么。因为\(a\)是个排列,元素互不相同,那么肯定就是按照每一段的第一个数的大小,越大的放在越前面。那么当\(a_1\lek\)的时候,显然先手会把以\(1\simk\)开头来划分段。因为否则存在一个开头\(>k\)的段,后手把其放......
  • CF932C Permutation Cycle
    题目传送门思路:个人认为构造题全靠感性理解,理解对了问题就迎刃而解了。(有点像做阅读理解)我们先感性地理解题目中所有变量和函数的含义。\(f\)函数是什么?当\(j\neq0\)时,\(f(i,j)=f(p_i,j-1)\),就是使\(j\)花费了\(1\)的代价,然后使\(i\)变为了\(p_i\)。这就......
  • C. Game on Permutation
    原题链接code#include<bits/stdc++.h>#definelllonglongusingnamespacestd;voidsolve(){intn;cin>>n;vector<int>p(n+4);for(inti=1;i<=n;i++)cin>>p[i];set<int>lose,win;//lose表示先移动必输的点f......
  • 题解:AT_abc352_d [ABC352D] Permutation Subsequence
    虽然比赛没打,但是想来水估值发表思路。题意给你一个\(1\simn\)的排列,让你从中找一段长为\(k\)的子序列,使得这个子序列中的元素排序后数值连续。分析题意转换一下,先用结构体存储每个元素的编号和数值,按照数值排序。于是这道题就成了:一个序列,让你求所有长\(k\)的子段中......
  • codeforces 1980 E. Permutation of Rows and Columns
    题目链接https://codeforces.com/problemset/problem/1980/E题意共输入\(T\)组测试用例,每组测试用例第一行输入两个整数\(n,m\),分别代表输入的数据的行数和列数,其中\(n*m\leq2*10^5\)。接下来输入两个\(n\)行\(m\)列的矩阵\(a,b\),对于每个矩阵中的元素\(x_{i,j}\)都是......