首页 技术 正文
技术 2022年11月16日
0 收藏 544 点赞 4,298 浏览 2452 个字

分析

题目要求在一共加入若干条边是的不同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;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,120
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,592
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,437
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,208
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,844
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,929