博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
51nod1370 排列与操作
阅读量:6226 次
发布时间:2019-06-21

本文共 2362 字,大约阅读时间需要 7 分钟。

性质:最终值域相同的一定是连续一段

花费最小?一定是值域个数个!并且当最后为i的数恰好只有i一个位置的时候,肯定选择不动,少花费一个

所以,我们考虑:每个最终方案在花费最小的方案下恰好被统计一次!

 

而对于一个合法的最终序列,考虑是怎样构造的

一定是先构造小的数,填充一些区间,再用大的数,可能覆盖一些小数的区间

换句话说,只要每个数的能填充这一段区间,就是合法的

也就是这个区间不能存在比这个数大的数!

有了这个发现,DP状态和转移就容易设计了

 

连续一段好处理,但是怎么知道之前没有出现过这个数?

还和位置有关,所以考虑顺序DP,到了i位置,考虑a[i]在最终序列的出现情况

 

f[i][j][k]考虑完了前i个位置,最终序列确定了前j个,花费k次

1.f[i-1][i-1][k]->f[i][i][k]i单独一块,不花费

2.f[i-1][j'][k-1]->f[i][j][k]把[j'+1,j]都变成a[i],前提是[j'+1,j]没有比a[i]大的,可以提前找到[l,r]极大的区间都<=a[i]

特别地,当j=i的时候,j'<j-1,否则白白花费一个代价,不满足“每个最终方案在花费最小的方案下恰好被统计一次!”,我们在第一个转移考虑了,这样会算重

3.f[i-1][j][k]->f[i][j][k],a[i]这个数不会出现在值域集合内。直接覆盖

 

第2个用前缀和优化即可

#include
#define reg register int#define il inline#define fi first#define se second#define mk(a,b) make_pair(a,b)#define numb (ch^'0')#define pb push_back#define solid const auto &#define enter cout<
using namespace std;typedef long long ll;template
il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x);}template
il void output(T x){
if(x/10)output(x/10);putchar(x%10+'0');}template
il void ot(T x){
if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}template
il void prt(T a[],int st,int nd){ for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}namespace Miracle{const int N=202;const int mod=1e9+7;int n,m;int f[N][N][N],s[N][N][N];int a[N];int ad(int x,int y){ return x+y>=mod?x+y-mod:x+y;}void clear(){ memset(f,0,sizeof f);memset(s,0,sizeof s);}int main(){ int t;rd(t); while(t--){ clear(); rd(n);rd(m); for(reg i=1;i<=n;++i) rd(a[i]); f[0][0][0]=1; for(reg j=0;j<=n;++j) s[0][j][0]=1; for(reg i=1;i<=n;++i){ int l=i,r=i; while(l>1&&a[l-1]
=0&&l-2>=0) f[i][j][k]=ad(f[i][j][k],ad(s[i-1][j-2][k-1],mod-s[i-1][l-2][k-1])); else if(j-2>=0) f[i][j][k]=ad(f[i][j][k],s[i-1][j-2][k-1]); }else{ f[i][j][k]=ad(f[i][j][k],ad(s[i-1][j-1][k-1],l-2>=0?mod-s[i-1][l-2][k-1]:0)); } } f[i][j][k]=ad(f[i][j][k],f[i-1][j][k]); } } for(reg k=0;k<=m;++k){ for(reg j=0;j<=n;++j){ s[i][j][k]=f[i][j][k]; if(j) s[i][j][k]=ad(s[i][j][k],s[i][j-1][k]); } } } // for(reg i=0;i<=n;++i){ // for(reg j=0;j<=n;++j){ // for(reg k=0;k<=m;++k){ // // cout<<" i j k "<
<<" "<
<<" "<
<<" : "<
<<" s "<
<

 

转载于:https://www.cnblogs.com/Miracevin/p/10881304.html

你可能感兴趣的文章
非监督学习算法:异常检测
查看>>
jquery的checkbox,radio,select等方法总结
查看>>
Linux coredump
查看>>
Ubuntu 10.04安装水晶(Mercury)无线网卡驱动
查看>>
Myeclipes快捷键
查看>>
ToRPC:一个双向RPC的Python实现
查看>>
我的友情链接
查看>>
nginx在reload时候报错invalid PID number
查看>>
神经网络和深度学习-第二周神经网络基础-第二节:Logistic回归
查看>>
Myeclipse代码提示及如何设置自动提示
查看>>
c/c++中保留两位有效数字
查看>>
ElasticSearch 2 (32) - 信息聚合系列之范围限定
查看>>
VS2010远程调试C#程序
查看>>
[MicroPython]TurniBit开发板DIY自动窗帘模拟系统
查看>>
由String类的Split方法所遇到的两个问题
查看>>
Python3.4 12306 2015年3月验证码识别
查看>>
从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
查看>>
windows查看端口占用
查看>>
Yii用ajax实现无刷新检索更新CListView数据
查看>>
JDBC的事务
查看>>