Time Limit: 2 Seconds      Memory Limit: 65536 KB


Edward has a permutation {a1a2, … an}. He finds that if he connects each pair (aiaj) such that i < j and ai > aj, he will get a graph.

For example, if the permutation is {2, 3, 1, 4}, then 1 and 2 are connected and 1 and 3 are connected.

Edward lost his permutation, but he does know the connected components of the corresponding graph. He wants to know how many permutations will result in the same connected components.

Note that two vertices uv belong to the same connected component if there exists a sequence of vertices starting with u and ending with v such that every two subsequent vertices in the sequence are connected by an edge.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains two integers nm (1 ≤ m ≤ n ≤ 100000), indicating the length of the permutation and the number of connected components in the graph.

Each of the following m lines contains an integer ci which denotes the size of i-th connected component, followed by ci distinct integers vi,1vi,2, … vi,ci which denotes the connected component (1 ≤ civi,1vi,2, … vi,ci ≤ n).

It is guaranteed that every number will appear in exact one connected component and c1 + c2 + … + cm = n.

Output

For each case, output the answer modulo 786433.

Sample Input

2
4 4
1 1
1 2
1 3
1 4
4 2
3 1 2 3
1 4

Sample Output

1
3

Hint

For the second case, the three permutations is: {2, 3, 1, 4}, {3, 2, 1, 4}, {3, 1, 2, 4}.


Author: LIN, Xi
Source: The 12th Zhejiang Provincial Collegiate Programming Contest

动态规划 分治NTT优化

随意脑补一下可以发现构成连通块的数排序后一定是连续+1递增的一串,不然它们中肯定有数连到别的地方去。

设f[i]表示大小恰好为i的连通块的方案数首先列出一个简单粗暴的方程:

 $ f[i]=\sum_{j=1}^{i} A_{j}^{j} * f[i-j] $

 $ A_{j}^{j}=j!$

复杂度$O(n^2)$

注意到右边构成了一个卷积的形式,且每个f都只由比它小的f计算得到。

于是可以愉快地用分治NTT优化DP

(前置技能:CDQ分治)

分治NTT理解了以后其实挺简单的,利用CDQ分治计算整个序列,当处理一个区间时,该区间的前一半已经被算完了,只需要把前一半的项卷积一下,答案累加到下标对应的后一半位置去,如此递归分治即可。

注意NTT的数组空间要开到(mid-l+1)的两倍。刚开始想当然觉得for(N=1,len=0;N<=m;N<<=1)等价,实际上这样做的话N会停在某个比size大,比2*size小的2的幂上

786433的原根是10  ←不知为什么记成11,调了半天

 /*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;
const int mod=;
const int G=;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
LL fac[mxn];
void init(){
fac[]=;
for(int i=;i<mxn;i++)fac[i]=(LL)fac[i-]*i%mod;
return;
}
LL ksm(LL a,LL k){
int res=;
while(k){
if(k&)res=(LL)res*a%mod;
a=(LL)a*a%mod;
k>>=;
}
return res;
}
LL a[mxn<<],b[mxn<<];
int N,len,rev[mxn<<];
void NTT(LL *a,int flag){
for(int i=;i<N;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int i=;i<N;i<<=){
int p=i<<;
LL gn=ksm(G,(flag==)?(mod-)/p:(mod-)-(mod-)/p);
for(int j=;j<N;j+=p){
LL g=;
for(int k=;k<i;k++,g=(LL)g*gn%mod){
LL x=a[j+k],y=g*a[j+k+i]%mod;
a[j+k]=(x+y)%mod;
a[j+k+i]=(x-y+mod)%mod;
}
}
}
if(flag==-){
LL INV=ksm(N,mod-);
for(int i=;i<N;i++)a[i]=(LL)a[i]*INV%mod;
}
return;
}
LL f[mxn];
void solve(int l,int r){
if(l==r){
f[l]=((fac[l]-f[l])%mod+mod)%mod;
//当l==r时,比l小的f全都算完了,可以得出f[l]=fac[l]-f[l]
return;
}
int i,j,mid=(l+r)>>;
solve(l,mid);//先算前一半
int m=(mid-l+)<<;//空间开两倍
for(N=,len=;N<=m;N<<=)len++;
for(i=;i<N;i++)rev[i]=(rev[i>>]>>)|((i&)<<(len-));
for(i=;i<N;i++)a[i]=b[i]=;
for(i=l;i<=mid;i++)//为了节省空间,将每一项左移l位计算
a[i-l]=f[i];
for(i=l;i<=r;i++)b[i-l]=fac[i-l];
//
NTT(a,);NTT(b,);
for(i=;i<N;i++)a[i]=(LL)a[i]*b[i]%mod;
NTT(a,-);
for(i=mid+;i<=r;i++){//将贡献累加到右半边
(f[i]+=a[i-l])%=mod;
}
solve(mid+,r);
return;
}
int n;
int num[mxn];
bool check(int x){
sort(num+,num+x+);
for(int i=;i<=x;i++){
if(num[i]!=num[i-]+)return ;
}
return ;
}
int main(){
int i,j;
init();
f[]=;
solve(,);
int T=read(),m;
while(T--){
n=read();m=read();
bool flag=;
LL ans=;
for(i=;i<=m;i++){
int sz=read();
for(j=;j<=sz;j++)num[j]=read();
if(!check(sz))flag=;
ans=(ans*f[sz])%mod;
}
if(!flag)puts("");
else printf("%lld\n",ans);
}
return ;
}

最新文章

  1. classpath: VS classpath*:
  2. Loader加载器
  3. 18Mybatis_动态sql_foreach
  4. JQUERY 一些技巧在实际中的应用
  5. ITERATOR(迭代器)设计模式
  6. NSOperation使用系统提供子类的方法--处理复杂任务
  7. STM32启动文件的选择
  8. MySQL学习笔记(3) - 查询服务器版本,当前时间,当前用户
  9. Sublime-text 自己定义快捷键攻略
  10. JS基础——数组总结
  11. Java IO详解(六)------序列化与反序列化(对象流)
  12. SNS团队Beta阶段第二次站立会议(2017.05.23)
  13. Mysql中字符集总结
  14. 第二篇 Flask 中的 Render Redirect HttpResponse
  15. 重装系统windows
  16. width多少,超过了用....表示
  17. SeekBar
  18. Android - 富文本编辑器
  19. 20155320 Exp6 信息搜集与漏洞扫描
  20. CF954I Yet Another String Matching Problem

热门文章

  1. LintCode-4.丑数 II
  2. TCP系列31—窗口管理&amp;流控—5、TCP流控与滑窗
  3. idea快捷键操作
  4. 【Linux】- ps 命令
  5. perf打印调用栈的过程
  6. mysql 重置 root 密码
  7. [OS] 操作系统错题集
  8. KeyPress 和KeyDown 、KeyPress之间的区别
  9. 【bzoj1231】[Usaco2008 Nov]mixup2 混乱的奶牛 状态压缩dp
  10. 楼房 洛谷1382 &amp;&amp; codevs2995