【ZJOI2016&&BZOJ4574】【NOIP模拟】作弊(DP&&随机数据)
来源:互联网 发布:淘宝网韩版女装秋季 编辑:程序博客网 时间:2024/05/21 22:41
Description
Solution
一开始这道题就看错题了,我直接用一轮的期望作为下一轮的值,结果还以为很容易就能用n^3搞出来,结果搞了半天。
因为最后序列的答案不会超过原序列的最大值,所以我们可以考虑对原序列离散化一下,然后考虑每个位置最后的值是原序列第k大的期望,那么我们可以设sum[i][j]表示第i个点值小于等于序列中第j大的方案是多少,然后用sum[i][j]-sum[i][j-1]就是当前的位置的值等于序列中的第j大的方案数是多少。
我们要考虑怎么求这个值。
那么我们可以求第i轮,[L,R]区间的值小于等于x的方案数,x是当前要求区间的最大值。
我们对于一个x,可以用一个极大的区间[l,r]来表示,就是当前[l,r]区间的最大值是x,那么l-1或r+1的值大于x。这个可以预处理出来。
然后对于第k轮的极大区间[l,r],我们来分类讨论一下上一轮的极大区间的可能的情况。
1、上一次的极大区间是[u,j],那么就是说我们的操作区间是[1~u-1,i-1],这样可以让[u,i-1]这段的值提升,让极大区间缩小(现在考虑的极大区间与x无关,只是单纯的考虑极大区间,就是l-1和r+1的值都是大于中间的最大值的)
2、极大区间是[i,v],和上面类似
3、极大区间是[i,j],那么可以操作一段[u,v]这段[u,v]可以完全被[i,j]包含或或者不相交,那么这个方案数是可以直接算的。
然后可以通过上面算出的f来算出sum值。
注意求sum值的时候,因为数字不是连续的,所以有一些值是0,要找到前面第一个不是0的地方减掉。
然后还要卡一下常,注意在n^3里面是不能带mod的,这样会很慢。
在随机数据下这个方法是n^3的,理论复杂度虽然n^4……
Code
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=507,mo=998244353;ll i,j,k,t,n,m,ans,p,q,num;ll f[2][maxn][maxn],sum[maxn][maxn],b[maxn],l[maxn],r[maxn],c[maxn],d[maxn];struct node{ ll x,y;}a[maxn];bool cmp(node x,node y){return x.x<y.x;}ll qsm(ll x,ll y){ ll z=1; for(;y;y/=2,x=x*x%mo)if(y&1)z=z*x%mo; return z;}void solve(int x,int L,int R){ int i,j,k,u,v; ll t; p=0; fo(i,L,R)fo(j,i,R)f[0][i][j]=0; f[0][L][R]=1; fo(k,1,m){ q=(p^1); fo(j,L,R){ t=0; fo(i,L,j){ f[q][i][j]=t; t=t+f[p][i][j]*(i-1); } } fo(i,L,R){ t=0; fod(j,R,i){ f[q][i][j]=(f[q][i][j]+t+(b[i-1]+b[n-j]+b[j-i+1])*f[p][i][j])%mo; t=t+f[p][i][j]*(n-j); } } p=q; } fo(i,L,R){ t=0; fod(j,R,i){ t=(t+f[p][i][j])%mo; sum[j][x]=(sum[j][x]+t)%mo; } }}int main(){ scanf("%lld%lld",&n,&m); fo(i,1,n)scanf("%lld",&a[i].x),a[i].y=i,b[i]=i*(i+1)/2; sort(a+1,a+1+n,cmp); num=1;d[a[1].y]=1;c[1]=a[1].x; fo(i,2,n){ if(a[i].x!=a[i-1].x)++num; d[a[i].y]=num,c[num]=a[i].x; } fo(i,1,n){j=i;while(j>1&&d[i]>=d[j-1])j=l[j-1];l[i]=j;} fod(i,n,1){j=i;while(j<n&&d[i]>=d[j+1])j=r[j+1];r[i]=j;} fo(i,1,n)solve(d[i],l[i],r[i]); fo(i,1,n){ ans=0;t=0; fo(j,1,num){ if(!sum[i][j])continue; sum[i][j]=sum[i][j]-t; ans=(ans+sum[i][j]*c[j]%mo)%mo; t=(t+sum[i][j])%mo; } ans=(ans+mo)%mo; ans=ans*qsm(qsm(n*(n+1)/2,m)%mo,mo-2)%mo; printf("%lld\n",ans); }}
- 【ZJOI2016&&BZOJ4574】【NOIP模拟】作弊(DP&&随机数据)
- 【BZOJ4574】【Zjoi2016】线段树 dp
- bzoj4574 [Zjoi2016]线段树 DP
- bzoj4574: [Zjoi2016]线段树
- BZOJ4574: [Zjoi2016]线段树
- [bzoj4574][UOJ#196][ZJOI2016]线段树
- #bzoj2933#【重庆市NOIP模拟赛】数据(DP线段树优化 or DP堆优化 + 证明)
- [noip模拟赛]祖先(dp)
- [noip模拟赛]二进制(dp)
- [noip模拟赛]敲砖块(dp)
- 【NOIP 模拟题】掷骰子(dp)
- 【NOIP 模拟题】[T1] 等差数列(dp)
- (noip 模拟 染色)<树形DP>
- #NOIP模拟赛#排列问题(DP)
- #NOIP模拟赛#TSP(树型DP)
- 【NOIP模拟】赤壁情(DP)
- NOIP模拟:乘积(状压DP)
- [NOIP 模拟]潜水员 DP
- C++ 单链表操作
- JDBC详细总结
- C语言 if条件判断中包含语句块
- 全排列、子集
- js中Event 对象 target 与 currentTarget的应用
- 【ZJOI2016&&BZOJ4574】【NOIP模拟】作弊(DP&&随机数据)
- 第二章 Java内存区域与内存溢出异常
- 网易疯狂队列
- 2.计算机组成原理笔记二发展应用及相关知识
- 自然语言学习心得2
- C++基础之指针作为函数的参数
- Centos7.x
- Yum安装 MYSQL
- loadrunner Web_类函数之web_cache_cleanup()