有标号的DAG图计数1~4

前言

我什么都不会,菜的被关了起来。

有标号的DAG图I

Solution

考虑递推,设\(f_i\)表示i个点的答案,显然这个东西是可以组合数+容斥递推?

设\(f_i\)表示i个点的答案,我们考虑假设现在有j个点入度为1,那么可以选出的点就是一个组合数\(C_i^j\),边的可能性有两种,对应的就是\(2^{j*(i-j)}\),然后接着搞,肯定这样子算会有重复的,所以容斥一下然后和以前的答案乘起来就好了。

\(f_i=\sum_{j=1}^{i}f_{i-j}*-1^{j-1}*C_i^j*2^{j*(i-j)}\)

然后就可以递推了。

上面虽然不是瞎扯,但是完全过不了本题 90分了解一下

所以需要运用的是什么?

当然是预处理啊(辣鸡出题人卡常数)

代码实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi(){
    int f=1,sum=0;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return f*sum;
}
const int Mod=1e4+7;
int c[5010][5010],f[5010],two[25000010];
int main(){
    re int n=gi();two[0]=1;
    for(int i=1;i<=n*n/4;i++){
        two[i]=two[i-1]<<1;
        if(two[i]>=Mod)two[i]-=Mod;
    }
    c[0][0]=1;
    for(re int i=1;i<=n;i++){
        c[i][0]=1;
        for(re int j=1;j<=n;j++){
            c[i][j]=(c[i-1][j]+c[i-1][j-1]);
            if(c[i][j]>=Mod)c[i][j]-=Mod;
        }
    }
    f[0]=f[1]=1;
    for(re int i=2;i<=n;i++)
        for(re int j=1,d=1;j<=i;j++,d=-d){
            f[i]+=(ll)(c[i][j]*f[i-j]%Mod*two[j*(i-j)]%Mod*d)%Mod;
            while(f[i]<0)f[i]+=Mod;
            while(f[i]>=Mod)f[i]-=Mod;
        }
    printf("%d\n",f[n]);
    return 0;
}

有标号的DAG图计数II

Solution

考虑上面的式子怎么搞?

发现如果想要卷积优化肯定只能够把2的次方拆开啊。
\[
j*(i-j)=i*j-j^2
\=\frac{i^2}{2}-\frac{j^2}{2}-\frac{(i-j)^2}{2}
\]

化成这个形式直接二次剩余随便搞就好了。

P.S:如果不会多项式求逆就看这个

代码实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
const int N=300010,Mod=998244353,REM=882049182;
int r[N],c[N],F[N],G[N],inv[N],jc[N],jcn[N];
int qpow(int a,int b){int ret=1;while(b){if(b&1)ret=(ll)ret*a%Mod;a=(ll)a*a%Mod;b>>=1;};return ret;}
inline int gi(){
    int f=1,sum=0;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return f*sum;
}
void NTT(int *P,int opt,int limit){
    for(int i=0;i<limit;i++)if(i<r[i])swap(P[i],P[r[i]]);
    for(int i=1;i<limit;i<<=1){
        int w=qpow(3,(Mod-1)/(i<<1));
        for(int p=i<<1,j=0;j<limit;j+=p){
            int W=1;
            for(int k=0;k<i;k++,W=(1ll*W*w)%Mod){
                int X=P[j+k],Y=(ll)P[i+j+k]*W%Mod;
                P[j+k]=(X+Y)%Mod;P[i+j+k]=(X-Y+Mod)%Mod;
            }
        }
    }
    if(opt==-1){
        reverse(P+1,P+limit);
        for(int i=0,inv=qpow(limit,Mod-2);i<limit;i++)P[i]=1ll*P[i]*inv%Mod;
    }
}
void Inv(int *a,int *b,int len){
    if(len==1){b[0]=qpow(a[0],Mod-2);return;}
    Inv(a,b,(len+1)>>1);
    int l=0,limit=1;
    while(limit<(len<<1))limit<<=1,l++;
    for(int i=0;i<limit;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    for(int i=0;i<limit;i++)c[i]=a[i];
    for(int i=len;i<limit;i++)c[i]=0;
    NTT(c,1,limit);NTT(b,1,limit);
    for(int i=0;i<limit;i++)b[i]=1ll*(2-1ll*c[i]*b[i]%Mod+Mod)%Mod*b[i]%Mod;
    NTT(b,-1,limit);
    for(int i=len;i<limit;i++)b[i]=0;
}
int main(){
    int n=gi();
    jc[0]=jcn[0]=inv[1]=1;
    for(int i=1;i<=n;i++)jc[i]=(ll)jc[i-1]*i%Mod;
    for(int i=2;i<=n;i++)inv[i]=(ll)(Mod-Mod/i)*inv[Mod%i]%Mod;
    for(int i=1;i<=n;i++)jcn[i]=(ll)jcn[i-1]*inv[i]%Mod;
    G[0]=1;
    int Limit=1;while(Limit<=n)Limit<<=1;int t=qpow(REM,Mod-2);
    for(int i=1;i<Limit;i++)G[i]=1ll*jcn[i]*qpow(t,1ll*i*i%(Mod-1))%Mod;
    for(int i=1;i<Limit;i++)if(i&1)G[i]=Mod-G[i];
    Inv(G,F,Limit);
    printf("%lld\n",1ll*F[n]*jc[n]%Mod*qpow(REM,1ll*n*n%(Mod-1))%Mod);
    return 0;
}

原文地址:https://www.cnblogs.com/cj-gjh/p/10284682.html

时间: 2024-07-30 16:58:20

有标号的DAG图计数1~4的相关文章

有标号的DAG/强连通图计数

COGS索引 一堆神仙容斥+多项式-- 有标号的DAG计数 I 考虑\(O(n^2)\)做法:设\(f_i\)表示总共有\(i\)个点的DAG数量,转移考虑枚举DAG上所有出度为\(0\)的点,剩下的点可以选择连向它,剩下的点之间也可以连边. 但是注意到这样子转移可能会存在剩下的点中有点没有出度的情况,考虑容斥解决:设枚举的出度为\(0\)的点的个数为\(i\)时的容斥系数为\(f_i\),那么一个实际上存在\(x\)个出度为\(0\)的点的DAG的贡献就是\(\sum\limits_{i=1}

有标号的DAG计数I~IV

有标号的DAG计数 最近心血来潮来写一写这个玩意儿. 请特别注意定义生成函数时下标的起始位置. 有标号的DAG计数I 求\(n\)点带标号\(DAG\)的数量模\(10007\).\(n\le5000\). 数据范围显然\(O(n^2)\).设\(f_i\)表示答案,枚举\(DAG\)中入度为零的点的数量\(j\),方案数为\(\binom ij\),将图拆成两个部分,前\(j\)个点向后\(i-j\)个点的连边任意,方案数为\(2^{j(i-j)}\),后\(j\)个点构成一张\(DAG\),

DAG图的拓扑排序 python

在DAG中DFS中顶点的出栈顺序即逆拓扑序. def topological_sort( graph ): is_visit = dict( ( node, False ) for node in graph ) li = [] def dfs( graph, start_node ): for end_node in graph[start_node]: if not is_visit[end_node]: is_visit[end_node] = True dfs( graph, end_n

POJ 1442 Air Raid(DAG图的最小路径覆盖)

题意: 有一个城镇,它的所有街道都是单行(即有向)的,并且每条街道都是和两个路口相连.同时已知街道不会形成回路. 可以在任意一个路口放置一个伞兵,这个伞兵会顺着街道走,依次经过若干个路口. 问最少需要投放几个伞兵,使得每个路口都被伞兵拜访过.并且要满足每个路口只能被一个伞兵拜访过. 思路: 裸DAG图的最小路径覆盖. DAG图的最小路径覆盖数 = 节点数 - 二分图最大匹配 代码: vector<int> graph[125]; int cx[125],cy[125]; bool bmask[

poj 2060 Taxi Cab Scheme(DAG图的最小路径覆盖)

题意: 出租车公司有M个订单. 订单格式:     hh:mm  a  b  c  d 含义:在hh:mm这个时刻客人将从(a,b)这个位置出发,他(她)要去(c,d)这个位置. 规定1:从(a,b)到(c,d)所花的时间为:abs(a-c)+abs(b-d). 规定2:一辆出租车如果要接单,必须在客人出发前1分钟(包括)以前接单. 问,最少派出多少辆出租车,可以完成所有任务. 思路: 把每一笔单看成一个点,如果完成第i个单后可以接到第j个单,则 i->j连上线. 则题为:求这个DAG图的最小路

Codeforces Round #455 (Div. 2) E. Coprocessor DAG图上dp

E. Coprocessor 题意:n 个任务,每个任务在 主 / 副 处理器上执行.每个任务可能依赖于其它的一些任务,副处理器每次可以处理多个任务.但如果一个任务要在副处理器上执行,那它所依赖的任务要么已执行完了,要么和它一起在这个副处理器上同时执行.问副处理器最少调用多少次. 直白一点讲,就是给出一个 DAG 图,n 个点, m 条边,每个点的权值为 0 或1 .操作:直接相互连通的权值为 1 的点可以一次处理掉. 问最少操作多少次. tags:因为是DAG 图,直接跑 dp dp[i] 表

无标定量|有标定量|谱图计数|XIC|AMT数据库|RT对对齐|母离子|子离子|SILVER|SRM|iBAQ|APEX|差异蛋白筛选|MaxQuant|PANDA|C-HPP

生物医学大数据-蛋白质定量 现今肽段定量效率存在巨大差异.比如相同质量蛋白质,但是肽段和蛋白信号不均一,在物理条件一致时,仅有70%的重复率,并且当重复次数变多时,overlapping在变少. 无标定量法 方法一是针对二级色谱的谱图计数,即统计二级色谱的数量,数量越多则蛋白丰度越高,但相同丰度蛋白也有不同的二级色谱数,所以算法目的是减少噪音. 方法二是针对一级色谱的离子流色谱峰XIC,即每个肽段的离子流色谱峰,可以取同一个肽段不同时间点上的信号强度,连接成峰,通过求该曲线的曲线下面积获取曲线信

给出一张DAG图,问最少加多少条有向边s.t.其强联通?

对于这个问题,可以简化成以下等价(证明略去)版本: 给出一张n个点的DAG图,图中的点出度(简称cd)或者入度(简称rd)为0,问最少加多少有向条边,s.t.其强联通? 定理1:对于一张n个点的DAG图,图中的点出度或者入度为0,最少只需要加n-1条有向边,就可以使其强联通. ·证明:初始状态下,加入第一条边,至多产生一个强联通分量,并且这个强联通分量中只包含两个点(证明略去).为了最小化加入有向边的数目,之后加入的有向边,一定不在这个强联通分量内部(因为它不会使得强联通分量的大小增加).而无论

有标号的DAG计数 III

Description 给定一正整数n,对n个点有标号的有向无环图进行计数,这里加一个限制:此图必须是弱连通图.输出答案 mod 10007 的结果. Solution 弱连通图即把边变成无向之后成为连通的图 考虑补集转换,用 \(DAG\) 的方案数减去不连通的方案数 设 \(f[i]\) 为大小为 \(i\) 的\(DAG\)的方案数 可以像 \(DAG I\) 那样求出来 \(g[i]\) 为弱连通图的方案数 \(g[n]=f[n]-\sum_{i=1}^{n}g[i]*f[i-j]*C_