• CF1466H


    CF1466H - Finding satisfactory solutions

    题目大意

    给定一组置换(a_i),现在对于每个元素(i)构造一个排列(p_i)

    有两类边

    1.(i ightarrow a_i)

    2.表示(i)(p_i)中所有在(i)前面出现的数(p_{i,j})连有向边

    现在要求最终的图里没有2类边出现在任何一个环上

    (nleq 40)

    图分析

    置换显然构成一堆环,答案只与每个置换环的大小有关

    把置换环缩点,2类边就构成置换环之间的拓扑图

    计算答案

    由于连边方式比较奇怪,(i)向任何(j)个点连边的方案数是(j!(n-1-j)!)

    考虑对于缩点之后的点进行拓扑图(dp),这是一个经典问题,参考 [CEOI2019] 游乐园 | [CEOI2019] Amusement Park

    因此需要一个枚举子集的过程

    而由于这题的特殊性,每个点实际上只与其对应置换环答案有关

    把一类点放在一起计算,枚举时额外乘上一个组合数即可

    实际实现时并不需要把所有点分类,可以只把大小为1,2的点拿出来,剩下的直接状压

    
    const int N=42,P=1e9+7;
    
    int n,m;
    int p[N],vis[N],C[N][N];
    int a[N],W[N][N],J[N],sz[1<<14];
    vector<vector<vector<int>>> dp; // 爽!!!
    
    int main() {
    	n=rd();
    	rep(i,1,n) p[i]=rd();
    	rep(i,0,n) rep(j,*C[i]=1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
    	rep(i,*J=1,n) J[i]=1ll*J[i-1]*i%P;
    	int c1=0,c2=0;
    	rep(i,1,n) if(!vis[i]) {
    		int c=0;
    		for(int j=i;!vis[j];j=p[j]) vis[j]=1,c++;
    		if(c==1) c1++;
    		else if(c==2) c2++;
    		else a[m++]=c;
    	}
    	rep(i,0,n-1) {
    		int t=0;
    		rep(j,0,i) t=(t+1ll*C[i][j]*J[j]%P*J[n-j-1])%P;
    		rep(j,*W[i]=1,n) W[i][j]=1ll*W[i][j-1]*t%P;
    	}
    	int A=(1<<m)-1;
    	rep(i,1,A) sz[i]=sz[i&(i-1)]+a[__lg(i&-i)];
    	dp.resize(c1+1);
    	rep(i,0,c1) {
    		dp[i].resize(c2+1);
    		rep(j,0,c2) dp[i][j].resize(A+1);
    	}
    	dp[0][0][0]=1;
    	rep(i,0,c1) rep(j,0,c2) rep(S,0,A) {
    		int c=sz[S]+i+2*j;
    		rep(a,0,c1-i) rep(b,0,c2-j) {
    			int R=A^S;
    			for(int T=R;;T=(T-1)&R) {
    				if(!a && !b && !T) break;
    				int d=sz[T]+a+b*2,parity=(__builtin_parity(T)^a^b)&1;
    				dp[a+i][b+j][S|T]=(dp[a+i][b+j][S|T]+1ll*(parity&1?1:-1)*W[c][d]*dp[i][j][S]%P*C[a+i][i]%P*C[b+j][j])%P;
    				if(T==0) break;
    			}
    		}
    	}
    	int ans=(dp[c1][c2][A]+P)%P;
    	printf("%d
    ",ans);
    }
    
    
    
    
    
  • 相关阅读:
    【转载】algorithm、numeric、functional
    spring-boot项目中通过maven下载依赖 导入自己的jar包
    spring-boot项目 idea maven编译失败 解决办法
    SVM核函数功能和选择——可视化 附源代码
    乳腺癌数据集上SVM核函数功能和选择的研究报告
    Python编程实验一 决策树实现结果预测
    操作系统课程设计 设备驱动
    操作系统课程设计 内核模块
    操作系统课程设计 系统调用
    操作系统课程设计 编译Linux内核
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14825172.html
Copyright © 2020-2023  润新知