zoukankan      html  css  js  c++  java
  • 题解 [AGC028D] Chords

    首先, 按照boshi巨佬的说法, 考虑每种联通块的出现次数。如果可以求出, 答案就是每种联通块的出现次数和。

    再按照boshi巨佬的说法, 一种定义联通块长相的方法是用编号最小的点和编号最大的点表示。

    于是设(f[l][r])(l, r)连通且外面的点不连接到里面的点, 里面的所有边都任意连接的方案数。

    由于(l, r)连通不是很好做, 所以就用任意连的方案数目减去连通的方案数目。

    (g[l][r])([l, r])内的点任意连接的方案数目, 有:

    (f[l][r] = g[F(l, r)] - sum f[l][k] imes g[F(k + 1, r)])

    (F(l, r))([l, r])之间没有被强制选的点数。

    那么显然这个方程就是在枚举本区间靠左的连通块的大小。

    容易发现的事实是, 合法的(f[l][r])区间的长度一定是个偶数。 然后(dp)前注意处理一下这个区间是否有连接到外面去的点就好了。

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    #define R register
    const int N = 600 + 5;
    const int P = 1e9 + 7;
    
    inline int read() {
    	int x = 0, f = 1; char a = getchar();
    	for(; a > '9' || a < '0'; a = getchar()) if(a == '-') f = -1;
    	for(; a >= '0' && a <= '9'; a = getchar()) x = x * 10 + a - '0';
    	return x * f;
    }
    
    int n, m;
    int g[N], fb[N], to[N];
    int f[N][N];
    
    inline int F(int l, int r) {
    	return r - l + 1 + fb[l - 1] - fb[r];
    }
    
    int main() {
    	#ifdef IN
    	//freopen(".in", "r", stdin);
    	//freopen(".out", "w", stdout);
    	#endif
    	n = read(); m = read(); n <<= 1;
    	for(R int i = 1; i <= m; i ++) {
    		int x = read(), y = read();
    		fb[x] = fb[y] = 1;
    		to[x] = y; to[y] = x;
    	}
    	for(R int i = 1; i <= n; i ++) fb[i] += fb[i - 1];
    	g[0] = 1;
    	for(R int i = 2; i <= n; i += 2) g[i] = 1LL * g[i - 2] * (i - 1) % P;
    	int ans = 0;
    	for(R int i = 1; i <= n; i ++) 
    		for(R int j = i; j <= n; j ++)
    			if((j - i) & 1) {
    				bool flg = 0;
    				for(R int k = i; k <= j; k ++)
    					if(to[k] && (to[k] < i || to[k] > j)) flg = 1;
    				if(flg) continue;
    				f[i][j] = g[F(i, j)];
    				for(R int k = i + 1; k < j; k ++)
    					f[i][j] = (f[i][j] - 1LL * f[i][k] * g[F(k + 1, j)] % P + P) % P;
    				ans = (ans + 1LL * f[i][j] * g[F(1, i - 1) + F(j + 1, n)] % P) % P;
    			}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    day12:crontab任务调度
    day11:组管理和权限管理
    day10:实用指令
    day09:用户管理
    day08:开机、重启和用户登录注销
    day07:vi和vim编辑器
    做一个简单的新闻客户端的一点准备
    Android学习笔记一之客户端连接服务器
    Struts2学习笔记二之Action
    Struts2学习笔记一之工作原理和struts.xml解析
  • 原文地址:https://www.cnblogs.com/clover4/p/13812681.html
Copyright © 2011-2022 走看看