• BZOJ 2169 连边 DP


    思路:DP

    提交:(1)次(课上刚讲过)

    题解:

    如果不管重边的话,我们设(f[i][j])表示连了(i)条边,(j)个点的度数是奇数的方案数,那么显然我们可以分三种状态转移:
    (f[i][j]+=f[i-1][j-2]*C_{n-j+2}^2;)连了两个偶点
    (f[i][j]+=f[i-1][j]*j*(n-j);)连了一奇一偶
    (f[i][j]+=f[i-1][j+2]*C_{j+2}^2;)连了两个奇点
    考虑如何处理重边:我们设(f[i][j])表示连了(i)条边,(j)个点的度数是奇数,并且没有重边方案数,那么除了上面的转移,还要多一个:
    (f[i][j]-=f[i-2][j]*(C_n^2-(i-2))),含义是任选一条边,假设被连了两次,那就相当于他没有连(不改变奇偶点的数量)。
    由于此时的(DP)的加边方案是有序的,即我们的 (DP) 限制了 (i) 这条边的出现,所以在转移完后要对方案数除以 (i)

    #include<cstdio>
    #include<iostream>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    template<class I> inline I g(I& x) { x=0;
    	register I f=1; register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
    } const int N=1010,M=10007;
    int n,m,k,tot,Inv[M],c[N],ans;
    int f[N][N];
    inline int C(int n) {return 1ll*n*(n-1)*Inv[2]%M;}
    inline void main() {
    	g(n),g(m),g(k); Inv[1]=1; for(R i=2;i<=min(k,M-1);++i) Inv[i]=M-M/i*Inv[M%i]%M;
    	for(R i=1,u,v;i<=m;++i) g(u),g(v),++c[u],++c[v]; for(R i=1;i<=n;++i) tot+=(c[i]&1); 
    	f[0][tot]=1; for(R i=1;i<=k;++i) for(R j=0;j<=n;++j) {
    		if(j>=2) f[i][j]+=f[i-1][j-2]*C(n-j+2)%M;
    		f[i][j]+=f[i-1][j]*j%M*(n-j)%M;
    		f[i][j]+=f[i-1][j+2]*C(j+2)%M;
    		if(i>=2) f[i][j]+=M-f[i-2][j]*(C(n)-(i-2))%M;
    		f[i][j]=1ll*f[i][j]*Inv[i%M]%M;
    	} printf("%d
    ",f[k][0]);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.08.16
    84

  • 相关阅读:
    webdriver 窗口切换
    element not visible 错误的原因和解决方式
    选择子数据,默认存储父数据 的校验方法
    What's jenkins And How to Install
    testng suite
    webdriver 选择下拉列表的操作
    webdriver 获取表格内的文案
    webdriver 定位表格元素
    webdriver 上传文件
    树上倍增求解LCA 模板
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11366110.html
Copyright © 2020-2023  润新知