zoukankan      html  css  js  c++  java
  • 【BZOJ2863】愤怒的元首(数数题)

    点此看题面

    大致题意:(n)个点的有标号(DAG)数目。

    前言

    不会数数的我实在太菜太菜。。。

    (DP)

    考虑(DAG)中必然存在入度为(0)的点,且去掉这些入度为(0)的点之后得到的依然是(DAG)

    于是,我们可以设(f_i)表示(i)个点的有标号(DAG)数目,枚举一个(j)表示至少存在(j)个入度为(0)的点。

    显然有此时的方案数为:

    [C_i^j imes 2^{j imes (i-j)} imes f_{i-j} ]

    即,枚举选出哪(j)个点,枚举入度为(0)的点和其他点之间的边是否选择,而其他点依然形成(DAG)可以直接从已有状态转移。

    看到至少,我们可以考虑容斥

    因此得到最终的转移方程:

    [f_i=sum_{j=1}^i(-1)^{j-1} imes C_i^j imes2^{j imes(i-j)} imes f_{i-j} ]

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 3000
    #define X 1000000007
    using namespace std;
    int n,f[N+5],pw[N*N+5],C[N+5][N+5];
    int main()
    {
    	RI i,j,op;for(scanf("%d",&n),pw[0]=i=1;i<=n*n;++i) (pw[i]=pw[i-1]<<1)>=X&&(pw[i]-=X);//预处理2的幂
    	for(C[0][0]=i=1;i<=n;++i) for(C[i][0]=j=1;j<=i;++j) C[i][j]=(C[i-1][j-1]+C[i-1][j])%X;//预处理组合数
    	for(f[0]=i=1;i<=n;++i) for(op=j=1;j<=i;op=X-op,++j)//枚举j
    		f[i]=(1LL*op*C[i][j]%X*pw[j*(i-j)]%X*f[i-j]+f[i])%X;//容斥转移
    	return printf("%d",f[n]),0;
    }
    
  • 相关阅读:
    关于抽象类
    封装.继承.多态
    构造方法
    String
    无参方法与有参方法
    类和对象
    使用分层实现业务处理(二)
    使用分层实现业务处理(一)
    序列化Serializable接口
    用JSP从数据库中读取图片并显示在网页上
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2863.html
Copyright © 2011-2022 走看看