zoukankan      html  css  js  c++  java
  • AGC030F

    AGC030F

    给定 (N),现在有一个长度为 (2N) 的序列 (A),其构成一个 (1sim 2N) 的排列,部分位置的值已经给出。

    (B_i=min (A_{2i-1},A_{2i}))

    求可能的 (B) 序列的数量,答案对 (10^9+7) 取模。

    (Nle 300)

    Solution

    思维好题。

    假设 (A_{2i-1},A_{2i}) 确定了,那么 (B_i) 确定了。

    我们可以将两个值删去。

    否则假设只确定了一个,相当于说明 (B_ile x),我们再 (x) 处进行标记

    从值域上考虑,我们发现问题等价于选择一些点作为 (min),然后将这些 (min)(B) 数组进行配对,求合法的方案数。

    由于后面位置的限制较松,考虑从后往前 Dp,设 (f_{i,j,k}) 表示考虑到权值 (i),当前有 (j) 个普通位置需要往前匹配,(k) 个限制 (B) 需要往前匹配的方案数。

    当然,由于没有匹配限制 (B)(min) 节点还需要匹配其余的 (B) 序列,所以答案需要乘以 ((n-m)!)

    转移是 naive 的,复杂度为 (O(N^3))

    启示:对于 Dp 进行考虑的时候,可以对限制和规则进行观察,有的时候从后往前 Dp 即可解决问题,例如 AGC012F 和 AGC030F

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
    #define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
    #define re register
    #define int long long
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int P = 1e9 + 7 ; 
    const int N = 300 + 5 ; 
    int n, m, D, A[N * 2], d[N * 2], L[N * 2] ; 
    int dp[N * 2][N * 2][N], f[N][N] ;
    void inc(int &x, int y) {
    	((x += y) >= P) && (x -= P) ; 
    }
    signed main()
    {
    	n = gi(), m = n * 2, D = n ;
    	rep( i, 1, m ) A[i] = gi() ; 
    	for(re int i = 1; i < m; i += 2 ) {
    		int u = A[i], v = A[i + 1] ;
    		if( u < 0 && v < 0 ) continue ; 
    		if( u > 0 && v > 0 ) -- D, d[u] = 1, d[v] = 1 ; 
    		else u = max( u, v ), L[u] = 1, -- D ; 
    	}
    	dp[m + 1][0][0] = 1 ; 
    	for(re int i = m; i >= 1; -- i) {
    		if(d[i]) 
    			rep( j, 0, m ) rep( k, 0, n ) dp[i][j][k] = dp[i + 1][j][k] ;
    		else if( L[i] ) 
    			rep( j, 0, m ) rep( k, 0, n ) 
    				inc( dp[i][j][k], dp[i + 1][j + 1][k] ),
    				inc( dp[i][j][k + 1], dp[i + 1][j][k] ) ;
    		else 
    			rep( j, 0, m ) rep( k, 0, n ) 
    				inc( dp[i][j][k], dp[i + 1][j][k + 1] * (k + 1) % P ),
    				inc( dp[i][j + 1][k], dp[i + 1][j][k] ),
    				inc( dp[i][j][k], dp[i + 1][j + 1][k] ) ;
    	}
    	int ans = dp[1][0][0] ; 
    	rep( i, 1, D ) ans = ans * i % P ; 
    	cout << ans << endl ; 
    	return 0 ;
    }
    
    
  • 相关阅读:
    Java设计模式系列之策略模式
    设计模式系列之热身
    算术表达式系列之后缀表达式求值
    算术表达式系列之中缀表达式转后缀表达式
    Maven下使用Junit对Spring进行单元测试
    Windows命令行使用总结(持续更新)
    Eclipse中web项目部署至Tomcat步骤
    MyBatis保存完整日期的解决方法
    Redis(一)源码安装
    【集成学习】sklearn中xgboost模块中plot_importance函数(绘图--特征重要性)
  • 原文地址:https://www.cnblogs.com/Soulist/p/13768240.html
Copyright © 2011-2022 走看看