\(Description\)

有\(n\)个元素,对于每个元素\(x_i\)最多知道一个形如\(x_j < x_i\)或\(x_j=x_i\)的条件,问有多少合法的序列.合法的序列满足每个元素出现一次,任一相邻两元素之间有小于号或或等于号,并且所有条件全部满足,但是对于两个序列,如果只修改相等元素的位置能使得他们一样,则是他们为同一序列,答案队\(10^9\)取模

\(n<=100\)

\(Solution\)

认真读题后可以发现:

对于每个元素\(x_i\)最多知道一个形如\(x_j<x_i\)或\(x_j=x_i\)的条件

若\(x_j=x_i\)

将\((i,j)\)合并,

若\(x_j<x_i\),

将\(j\)连向\(i\)

最后建立一个超级根节点,将这个点连向所有入读为\(0\)的点

这样就是一棵树了.

用\(f[i][j]\)表示以\(i\)为根的子树中的元素能分\(j\)段,使\(j\)段每段相等的合法序列数

首先给出转移方程:

\[f[x][i]=f'[x][j]*f[v][k]*C_{i-1}^{j-1}*C_{j-1}^{k-i+j}
\]

\(f'[x]\)表示在\(v\)之前的\(f\)值

v为x的子树

\[C_{i-1}^{j-1}*C_{j-1}^{k-i+j}
\]

上面式子表示将\(j\)段和\(k\)段合并为\(i\)段的方案数.

至于为什么?

就是\(j-1\)放在\(x\)的方案数\(*v\)剩下的段余B合并的方案数:

\(Code\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
int c[1011][1011],f[1001][1001],siz[10011],dp[10010],head[10010],cnt;
struct node {
int to,next;
}a[10011];
void add(int x,int y){
a[++cnt].to=y,a[cnt].next=head[x],head[x]=cnt;
a[++cnt].to=x,a[cnt].next=head[y],head[y]=cnt;
}
void init(){
for(int i=0;i<=200;i++)
c[i][i]=c[i][0]=1;
for(int i=2;i<=200;i++)
for(int j=1;j<i;j++)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
void dfs(int x,int fa){
siz[x]=f[x][1]=1;
for(int e=head[x];e;e=a[e].next){
int v=a[e].to;
if(v==fa)
continue;
dfs(v,x);
memset(dp,0,sizeof(dp));
for(int i=1;i<=siz[x]+siz[v];i++)
for(int j=1;j<=siz[x];j++)
for(int k=1;k<=siz[v];k++){
int z=k-i+j;
if(z<0) continue;
(dp[i]+=f[x][j]*f[v][k]%mod*c[i-1][j-1]%mod*c[j-1][z]%mod)%=mod;
}
siz[x]+=siz[v];
for(int i=1;i<=siz[x];i++)
f[x][i]=dp[i];
}
}
int X[100001],Y[10001],pre[10001],flag[10010],bj[10010],vis[10010],fa[10010];
int find(int x){
return (x==pre[x])?x:pre[x]=find(pre[x]);
}
int find1(int x){
return (x==fa[x])?x:fa[x]=find1(fa[x]);
}
void join(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy)
pre[fx]=fy,fa[fx]=fy;
}
main(){
init();
int n=read(),m=read(),x,y;
char s;
for(int i=1;i<=n;i++)
pre[i]=i,fa[i]=i;
for(int i=1;i<=m;i++){
X[i]=read(),scanf("%c",&s),Y[i]=read();
if(s=='=')
flag[i]=1,join(X[i],Y[i]);
}
for(int i=1;i<=m;i++)
if(!flag[i]){
int fx=find(X[i]),fy=find(Y[i]);
add(fx,fy),vis[fy]++;
if(find1(X[i])==find1(Y[i]))
puts("0"),exit(0);
fa[find1(X[i])]=find1(Y[i]);
}
for(int i=1;i<=n;i++)
bj[find(i)]=1;
for(int i=1;i<=n;i++)
if(bj[i]&&!vis[i])
add(n+1,i);
dfs(n+1,0);
int ans=0;
for(int i=1;i<=siz[n+1];i++)
ans+=f[n+1][i],ans%=mod;
printf("%lld ",ans);
}

「HNOI 2015」实验比较的更多相关文章

  1. 「HNOI 2015」亚瑟王

    \(Description\) 有\(n\)张卡牌,每一张卡牌有\(p_i\)的概率发动,并造成\(d_i\)点伤害.一共有\(r\)轮,每一轮按照编号从小到大依次考虑,如果这张牌已经发动过则跳过该牌 ...

  2. 「HNOI 2015」菜肴制作

    题目链接 戳我 \(Description\) 有若干限制,需要求一个\(1\)到\(n\)的排列,每个限制\((x,y)\)表示\(x\)必须在\(j\)之前,并要求所求的排列满足所有限制并让\(1 ...

  3. 「HNOI 2015」落忆枫音

    题目链接 戳我 \(Description\) 给一张\(n\)割点\(m\)条边的\(DAG\),保证点\(1\)不存在入边,现在需要在\(DAG\)中加入一条不在原图中的边\((x,y)\),求这 ...

  4. LOJ#3054. 「HNOI 2019」鱼

    LOJ#3054. 「HNOI 2019」鱼 https://loj.ac/problem/3054 题意 平面上有n个点,问能组成几个六个点的鱼.(n<=1000) 分析 鱼题,劲啊. 容易想 ...

  5. GDOI#345. 送礼物「JSOI 2015」01分数规划+RMQ

    题目描述 JYY和CX的结婚纪念日即将到来,JYY来到萌萌开的礼品店选购纪念礼物.萌萌的礼品店很神奇,所有出售的礼物都按照特定的顺序都排成一列,而且相邻的礼物之间有一种神秘的美感.于是,JYY决定从中 ...

  6. 「HNOI 2019」白兔之舞

    一道清真的数论题 LOJ #3058 Luogu P5293 题解 考虑$ n=1$的时候怎么做 设$ s$为转移的方案数 设答案多项式为$\sum\limits_{i=0}^L (sx)^i\bin ...

  7. 「HNOI 2016」 序列

    \(Description\) 给你一个序列,每次询问一个区间,求其所有子区间的最小值之和 \(Solution\) 这里要用莫队算法 首先令\(val\)数组为原序列 我们考虑怎么由一个区间\([l ...

  8. 「HNOI 2014」 江南乐

    \(Description\) \(n\)堆石子,每堆石子有\(s_i\)个,两个人轮流操作,每次可以将一对不少于\(F\)的石子尽量平均分成\(m\)堆,\(m\)每次自选,不能操作者输.共有\(T ...

  9. 「HNOI 2014」 画框

    题目链接 戳我 \(Solution\) 这一题很像最小乘积生成树.只是把\(kruskal\)变为了\(km\)/费用流 现在来讲一讲最小乘积生成树.首先将\(\sum a_i\)和\(\sum b ...

随机推荐

  1. WPF 实现指定UI控件截图

    using System.Windows.Media.Imaging; using System.IO; private void SaveToImage(FrameworkElement ui, s ...

  2. leetcode9

    public class Solution { public bool IsPalindrome(int x) { ) { return false; } var str = x.ToString() ...

  3. Remove “Quick Access” entry in Eclipse Juno

    Here is a quick hack which doesn't require any plugin installation, instead you just need to add a f ...

  4. UGUI 事件穿透规则

    UGUI事件分为两大类:点击和拖拽. 点击包括 pointerdown, pointerup. 拖拽包括 begindrag, drag, enddrag. 点击事件无穿透:只会被最上层UI响应,不会 ...

  5. 【328】Python 控制鼠标/键盘+图片识别 综合应用

    本文是基于 [267]实现跨网络传数据 的基础上的,由于在弹出 putty 之后,需要手动输入命令(pass.sh.get.sh)来实现数据的传递,另外就是处理完之后需要手动关闭 putty,本文解决 ...

  6. MVC表单提交写法1

    初学MVC,感觉跟以前的aspx页面差别很大,我们就先来看看MVC的表单是怎么提交的吧. 现在我们用一个最简单的例子来看一看MVC是怎么提交表单的(这一个例子中,我们的关注点是如何提交表单,所以不涉及 ...

  7. unity5-GI是什么?

    GI是什么? GI =直接光照+间接光照+环境光+反射光.直接光照先不用说了,间接光照是光线在物体上反射所带来的光照. 核心参数: 每个光源上的Bounce Intensity.环境光可以直接理解为你 ...

  8. Error while trying to retrieve text for error ORA-12154

    问题描述:vs中调试运行没有任何错误,但是发布到IIS中访问,就会报以上错误.IIS不会调试,所以一头雾水,不止错误在哪里. 分析:看到网上有人分析了Web.config模拟验证的问题恍然大悟: 原文 ...

  9. mysql添加表注释、字段注释、查看与修改注释

    1 创建表的时候写注释create table test1( field_name int comment '字段的注释')comment='表的注释'; 2 修改表的注释alter table te ...

  10. cocos2dx中使用tolua++使lua调用c++函数

    一直想学学cocos2dx中如何使用tolua++工具使得lua脚本调用C++函数,今天就来搞一下,顺便记录下来: 首先,我们打开cocos2dx-2.2.4中projects下的test的VS工程, ...