题面:vjudge传送门 ZOJ传送门

题目大意:给你一个排列,如果两个数构成了逆序对,就在他们之间连一条无向边,这样很多数会构成一个联通块。现在给出联通块内点的编号,求所有可能的排列数

推来推去容易发现性质,同一联通块内的点一定是连续标号的,否则无解

然后我就不会了

好神的$NTT$优化$DP$啊

根据上面的性质,联通块之间是互不影响的,所以我们对每个联通块分别统计答案再相乘

定义$f[i]$表示$i$个点构成的合法联通块,可能的排列数

一个合法联通块的所有元素一定在同一联通块内,说明不可能存在两个联通块,因此

$f[i]=i!-\sum f[j]*(i-j)!$

发现这是一个卷积的形式,用分治$NTT$求解即可

模数是一个原根是10的费马素数

别忘了判断无解的情况

  1. #include <cmath>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #define N1 (1<<18)+10
  6. #define il inline
  7. #define dd double
  8. #define ld long double
  9. #define ll long long
  10. using namespace std;
  11.  
  12. const int inf=0x3f3f3f3f;
  13. const ll p=;
  14. int gint()
  15. {
  16. int ret=,fh=;char c=getchar();
  17. while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
  18. while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
  19. return ret*fh;
  20. }
  21. ll qpow(ll x,ll y)
  22. {
  23. ll ans=;
  24. for(;y;x=x*x%p,y>>=) if(y&) ans=ans*x%p;
  25. return ans;
  26. }
  27.  
  28. namespace NTT{
  29.  
  30. ll a[N1],b[N1],c[N1],invwn[N1],mulwn[N1];
  31. int r[][N1];
  32. void Pre(int len,int L)
  33. {
  34. int i,j;
  35. for(j=;j<=L;j++) for(i=;i<(<<j);i++)
  36. r[j][i]=(r[j][i>>]>>)|((i&)<<(j-));
  37. for(i=;i<=len;i<<=) mulwn[i]=qpow(,(p-)/i), invwn[i]=qpow(mulwn[i],p-);
  38. }
  39. void NTT(ll *s,int len,int type,int L)
  40. {
  41. int i,j,k; ll wn,w,t;
  42. for(i=;i<len;i++) if(i<r[L][i]) swap(s[i],s[r[L][i]]);
  43. for(k=;k<=len;k<<=)
  44. {
  45. wn=(type>)?mulwn[k]:invwn[k];
  46. for(i=;i<len;i+=k)
  47. {
  48. for(j=,w=;j<(k>>);j++,w=w*wn%p)
  49. {
  50. t=w*s[i+j+(k>>)]%p;
  51. s[i+j+(k>>)]=(s[i+j]+p-t)%p;
  52. s[i+j]=(s[i+j]+t)%p;
  53. }
  54. }
  55. }
  56. }
  57. void Main(int len,int L)
  58. {
  59. int i,invl=qpow(len,p-);
  60. NTT(a,len,,L); NTT(b,len,,L);
  61. for(i=;i<len;i++) c[i]=a[i]*b[i]%p;
  62. NTT(c,len,-,L);
  63. for(i=;i<len;i++) c[i]=c[i]*invl%p;
  64. }
  65. void clr(int sz)
  66. {
  67. memset(a,,sz<<);
  68. memset(b,,sz<<);
  69. }
  70.  
  71. };
  72.  
  73. using NTT::a; using NTT::b; using NTT::c;
  74. ll f[N1],g[N1]; int de;
  75. void CDQ(int l,int r)
  76. {
  77. if(r-l<) return;
  78. if(r-l==){ f[l]=(g[l]+p-f[l])%p; return; }
  79. int mid=(l+r)>>,i,len,L;
  80. CDQ(l,mid);
  81. for(len=,L=;len<(mid-l)+(r-l)-;len<<=,L++);
  82. for(i=l;i<mid;i++) NTT::a[i-l]=f[i];
  83. for(i=;i<(r-l);i++) NTT::b[i]=g[i];
  84. NTT::Main(len,L);
  85. for(i=mid;i<r;i++) f[i]=(f[i]+NTT::c[i-l])%p;
  86. NTT::clr(len);
  87. CDQ(mid,r);
  88. }
  89. int T,n,m;
  90. int que[N1];
  91.  
  92. int main()
  93. {
  94. int i,j,x,y,len,L,mi,ma; ll ans;
  95. scanf("%d",&T); n=;
  96. for(i=,g[]=;i<n;i++) g[i]=g[i-]*i%p;
  97. for(len=,L=;len<n+n-;len<<=,L++);
  98. NTT::Pre(len,L);
  99. CDQ(,n);
  100.  
  101. while(T--){
  102.  
  103. n=gint(); m=gint(); ans=;
  104. for(i=;i<=m;i++)
  105. {
  106. x=gint(); mi=inf,ma=;
  107. for(j=;j<=x;j++) que[j]=gint(), mi=min(mi,que[j]), ma=max(ma,que[j]);
  108. if(ma-mi+!=x) ans=;
  109. ans=(ans*f[x])%p;
  110. }
  111. printf("%lld\n",ans);
  112.  
  113. }
  114. return ;
  115.  
  116. }

ZOJ 3874 Permutation Graph (分治NTT优化DP)的更多相关文章

  1. ZOJ 3874 Permutation Graph 分治NTT

    Permutation Graph Time Limit: 2 Seconds      Memory Limit: 65536 KB Edward has a permutation {a1, a2 ...

  2. ZOJ 3874 Permutation Graph ——分治 NTT

    发现每一块一定是按照一定的顺序的. 然后与标号无关,并且相同大小的对答案的影响相同. 然后列出递推式,上NTT+分治就可以了. 然后就可以与输入同阶处理答案了. #include <map> ...

  3. HDU 5279 YJC plays Minecraft (分治NTT优化DP)

    题目传送门 题目大意:有$n$个小岛,每个小岛上有$a_{i}$个城市,同一个小岛上的城市互相连接形成一个完全图,第$i$个小岛的第$a_{i}$个城市和第$i+1$个小岛的第$1$个城市连接,特别地 ...

  4. HDU 5322 Hope (分治NTT优化DP)

    题面传送门 题目大意: 假设现在有一个排列,每个数和在它右面第一个比它大的数连一条无向边,会形成很多联通块. 定义一个联通块的权值为:联通块内元素数量的平方. 定义一个排列的权值为:每个联通块的权值之 ...

  5. 【uoj#244】[UER #7]短路 CDQ分治+斜率优化dp

    题目描述 给出 $(2n+1)\times (2n+1)$ 个点,点 $(i,j)$ 的权值为 $a[max(|i-n-1|,|j-n-1|)]$ ,找一条从 $(1,1)$ 走到 $(2n+1,2n ...

  6. BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)

    BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...

  7. 4.13 省选模拟赛 树 树形dp 卷积 NTT优化dp.

    考试的时候 看到概率 看到期望我就怂 推了一波矩阵树推自闭了 发现 边权点权的什么也不是. 想到了树形dp 维护所有边的断开情况 然后发现数联通块的和再k次方过于困难. 这个时候 应该仔细观察一下 和 ...

  8. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  9. bzoj3672/luogu2305 购票 (运用点分治思想的树上cdq分治+斜率优化dp)

    我们都做过一道题(?)货币兑换,是用cdq分治来解决不单调的斜率优化 现在它放到了树上.. 总之先写下来dp方程,$f[i]=min\{f[j]+(dis[i]-dis[j])*p[i]+q[i]\} ...

随机推荐

  1. 神奇的JAVA多态

    以前理解了基本思想,这版本的演示和应用比较真实. 顺路下来抽象方法和类,接口,就顺理成章啦... JAVA文件放一块了,分别对照前一个帖子的文件名: ///////////////////////// ...

  2. Sigma Function 数学 因子求和

    Sigma function is an interesting function in Number Theory. It is denoted by the Greek letter Sigma ...

  3. cogs 10. 信号无错传输

    10. 信号无错传输 ★★☆   输入文件:dlj.in   输出文件:dlj.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 为提高传递信息的保密性和可靠性,两个军事 ...

  4. 进行mysql压力測试须要注意的几点

    1.填充測试数据比物理内存还要大,至少超过innodb_buffer_pool_size 值,不能将数据所有装载到内存中,除非你的本意就想測试全内存状态下的MySQL性能. 2.每轮測试完毕后,都重新 ...

  5. STM32的IO配置点灯

    1.led.c的详细的代码: /*----------------------------------------------------------*/ #include "led.h&q ...

  6. Codeforces Round #377 (Div. 2) D. Exams

    Codeforces Round #377 (Div. 2) D. Exams    题意:给你n个考试科目编号1~n以及他们所需要的复习时间ai;(复习时间不一定要连续的,可以分开,只要复习够ai天 ...

  7. hdu 1235 统计同成绩学生人数

    import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = ...

  8. Redis各种数据类型的使用场景

    Redis的六种特性 l Strings l Hashs l Lists l Sets l Sorted Sets l Pub/Sub Redis各特性的应用场景 Strings Strings 数据 ...

  9. graphviz.js的图形及属性简单用法

    digraph A { graph[bgcolor="cadetblue" label="图的标题" fontsize=48 fontcolor="g ...

  10. Nginx实战系列之功能篇----后端节点健康检查

    目前,nginx对后端节点健康检查的方式主要有3种,这里列出:   1.ngx_http_proxy_module 模块和ngx_http_upstream_module模块(自带)    官网地址: ...