分析

题目要求在一共加入若干条边是的不同B序列的个数;方便统计,我们不妨让一个B序列对应一种特定的操作来构造,具体如下

从1开始按从小到大加入点,始终维护一个顺序为加点次序的链;每次加入一条有向边

不会影响SCC个数的

1)连上新点:链末尾与新点连

2)连上废边:加上一条不改变强连通情况的边,不改变链

(两个决策每次必须只选一种,钦定为能加点加点,否则考虑连废边)

会影响的SCC个数

3)把链上与1强连通的部分(钦定为链的前缀)向后扩展若干

应注意到任意时刻SCC的数目为n-(j+1),n是图的点集大小,j是当前与1强连通的点集大小。

这样的构造与B序列是一一对应的,于是我们可以考虑计数dp,设f[i,j,k]为已经加入了i条边,与1强连通的链前缀长度为j+1,除此之外还有长度k的不同的B序列的个数。

转移和一些约束如下

f[0,0,0]=1

f[i,j,k]->f[i+1,j,k+1] j+1+k<n

f[i,j,k]->f[i+1,j,k] j+1+k==n且j*(j+1)+k(k-1)/2+(j+1)*k>i (注意是有向边哦)

f[i,j,k]->f[i+1,j+t,k-t] 0<t<=k 需要前缀和优化

实现

先留坑好了。 以下是暴力代码(80)

#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7; inline void add(int&x,int y) {
if((x+=y)>=mod) x-=mod;
} int n,now,nxt=1;
int f[2][401][401],t[401][401]; int main() {
scanf("%d",&n);
f[now][0][0]=1;
for(int i=0; i<n*(n-1); ++i,now=nxt,nxt^=1) {
for(int j=0; j<n; ++j) {
for(int k=0; j+k<n; ++k) {
if(!f[now][j][k]) continue;
if(j+1+k<n) add(f[nxt][j][k+1],f[now][j][k]);
else if(j*(j+1)+k*(k-1)/2+(j+1)*k>i) add(f[nxt][j][k],f[now][j][k]);
if(k>0) add(t[j+1][k-1],f[now][j][k]);
f[now][j][k]=0;
}
}
for(int j=0; j<n; ++j) {
for(int k=0; j+k<n; ++k) {
add(f[nxt][j][k],t[j][k]);
if(k>0) add(t[j+1][k-1],t[j][k]);
t[j][k]=0;
}
}
int ans=0;
for(int j=0; j<n; ++j) {
for(int k=0; j+k<n; ++k) {
add(ans,f[nxt][j][k]);
}
}
printf("%d ",ans);
}
return 0;
}

优化状态数目并吸氧的代码

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std; const int N=400+5;
const int mod=1e9+7; int n;
int now,nxt=1,f[2][N][N],t[N][N];
#define push(c,x,y) sta[c][++top[c]]=make_pair(x,y)
int mx,top[2],tmp[N];
pair<int,int> sta[2][20*N*N];
bool vis[N]; inline void add(int&x,int y) {
if((x+=y)>=mod) x-=mod;
}
int main() {
scanf("%d",&n);
f[now][0][0]=1;
push(now,0,0);
for(int i=0; i<n*(n-1); ++i,now=nxt,nxt^=1) {
top[nxt]=0;
for(int p=1; p<=top[now]; ++p) {
int j=sta[now][p].first;
int k=sta[now][p].second;
// printf("|%d,%d>,",j,k);
if(!f[now][j][k]) continue;
if(j+1+k<n) {
add(f[nxt][j][k+1],f[now][j][k]);
push(nxt,j,k+1);
} else if(j*(j+1)+k*(k-1)/2+(j+1)*k>i) {
add(f[nxt][j][k],f[now][j][k]);
push(nxt,j,k);
}
if(k>0) {
add(t[j+1][k-1],f[now][j][k]);
vis[j+k]=true;
}
f[now][j][k]=0;
}
int c=0,pre=top[nxt];
for(int s=0; s<n; ++s) if(vis[s]) {
vis[s]=false; tmp[++c]=s;
}
for(int j=0; j<n; ++j) {
for(int p=c; p; --p) {
int k=tmp[p];
if(k<0) break;
add(f[nxt][j][k],t[j][k]);
if(f[nxt][j][k]) push(nxt,j,k);
if(k>0) add(t[j+1][k-1],t[j][k]);
t[j][k]=0; tmp[p]--;
}
}
merge(sta[nxt]+1,sta[nxt]+pre+1,sta[nxt]+pre+1,sta[nxt]+top[nxt]+1,sta[nxt]+1); //归并
top[nxt]=unique(sta[nxt]+1,sta[nxt]+top[nxt]+1)-sta[nxt]-1;
int ans=0;
for(int p=1; p<=top[nxt]; ++p) {
add(ans,f[nxt][sta[nxt][p].first][sta[nxt][p].second]);
}
printf("%d ",ans);
}
return 0;
}

P5241 序列的更多相关文章

  1. P5241 序列(滚动数组+前缀和优化dp)

    P5241 序列 挺神仙的一题 看看除了dp好像没什么其他办法了 想着怎么构个具体的图出来,然鹅不太现实. 于是我们想办法用几个参数来表示dp数组 加了几条边肯定要的吧,于是加个参数$i$表示已加了$ ...

  2. 【夯实PHP基础】UML序列图总结

    原文地址 序列图主要用于展示对象之间交互的顺序. 序列图将交互关系表示为一个二维图.纵向是时间轴,时间沿竖线向下延伸.横向轴代表了在协作中各独立对象的类元角色.类元角色用生命线表示.当对象存在时,角色 ...

  3. Windows10-UWP中设备序列显示不同XAML的三种方式[3]

    阅读目录: 概述 DeviceFamily-Type文件夹 DeviceFamily-Type扩展 InitializeComponent重载 结论 概述 Windows10-UWP(Universa ...

  4. 软件工程里的UML序列图的概念和总结

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 软件工程的一般开发过程:愿景分析.业务建模,需求分析,健壮性设计,关键设计,最终设计,实现…… 时序图也叫序列图(交互图),属于软件 ...

  5. python序列,字典备忘

    初识python备忘: 序列:列表,字符串,元组len(d),d[id],del d[id],data in d函数:cmp(x,y),len(seq),list(seq)根据字符串创建列表,max( ...

  6. BZOJ 1251: 序列终结者 [splay]

    1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3778  Solved: 1583[Submit][Status][Discu ...

  7. 最长不下降序列nlogn算法

    显然n方算法在比赛中是没有什么用的(不会这么容易就过的),所以nlogn的算法尤为重要. 分析: 开2个数组,一个a记原数,f[k]表示长度为f的不下降子序列末尾元素的最小值,tot表示当前已知的最长 ...

  8. [LeetCode] Sequence Reconstruction 序列重建

    Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. Th ...

  9. [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列

    Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...

随机推荐

  1. 「JOISC 2018 Day 3」比太郎的聚会

    题解: 很套路的题目 我们按照询问中的不算的个数是否大于$block$分类 如果大于,就$O(n)dp$一下 如果小于,就预处理出到每个点前$block$小的点 $block取\sqrt{n}$的话复 ...

  2. c/c++再学习:排序算法了解

    1.冒泡排序 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成. ...

  3. 【MSVC】_invalid_parameter和_invoke_watson

    最近遇到一个崩溃问题,崩溃在CRT中,最后调用的函数是_invoke_watson.调用关系大概如下: _invoke_watson _invalid_parameter _invalid_param ...

  4. windows jdk安装

    先去官网下载安装包 x86 32位 x64 64位 下载地址 安装jdk 安装目录默认c盘 配置系统环境 JAVA_HOME环境变量.作用:它指向jdk的安装目录,Eclipse/NetBeans/T ...

  5. SQL 获取表结构

    select [表名]=c.Name, [表说明]=isnull(f.[value],''), [列序号]=a.Column_id, [列名]=a.Name, [列说明]=isnull(e.[valu ...

  6. Python+Tkinter 实现计算器功能

    #=================================================================================== import tkinter ...

  7. 支持不同Android设备,包括:不同尺寸屏幕、不同屏幕密度、不同系统设置

    Some of the important variations that you should consider include different languages, screen sizes, ...

  8. UWB DWM1000 跟随小车原理---一张图演示

    更多内容参考论坛:bphero.com.cn

  9. JTAG各类接口针脚定义及含义

    注:转自 揽月阁 JTAG有10pin的.14pin的和20pin的,尽管引脚数和引脚的排列顺序不同,但是其中有一些引脚是一样的,各个引脚的定义如下. 一.引脚定义 Test Clock Input ...

  10. xampp访问phpmyadmin访问不了

    我的xampp版本是xampp-linux-x64-5.6.15-2-installer.run, 浏览器输入“我的ip/phpmyadmin”出现如下问题: Access forbidden! Ne ...