[CTSC2018]青蕈领主

题解

首先,连续段要知道结论:

连续段要么不交,要么包含

所以是一棵树!每个位置的father是后面第一个包含它的

树形DP!

设dp[x],x为根的子树,(设管辖的区间长度为len,也即L[x]),用1~len的数填充,满足L的方案数

也就是,每个son内部合法,

给每个son分配标号区间,使得相邻儿子不会再接在一起

不会再接在一起?

所以可以把每个儿子看成单独一个点,就划归成了:1,1,1,1,...len的方案数!

设f[i]表示,长度为i+1的1,1,1,1....i+1的序列的合法方案数。

$dp[x]=(\Pi dp[son])\times f[L[x]]$

归纳一下,可得$ans=\Pi f[|son(x)|]$,$|son(x)|$表示x的儿子个数

求f[n]?

考虑变成排列的逆!

(也就是把映射矩阵的横纵坐标意义交换)

这样,n+1成为了天然的分割点。

f[n-1]中,填入1,

要么之前合法。

要么1分开了一些东西

|son(x)|可以直接单调栈

注意,Poly每次clear需要重新resize

#include<bits/stdc++.h>
#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<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
namespace Modulo{
const int mod=;
int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
void inc(int &x,int y){x=ad(x,y);}
int sub(int x,int y){return ad(x,mod-y);}
int mul(int x,int y){return (ll)x*y%mod;}
void inc2(int &x,int y){x=mul(x,y);}
int qm(int x,int y=mod-){int ret=;while(y){if(y&) ret=mul(x,ret);x=mul(x,x);y>>=;}return ret;}
template<class ...Args>il int ad(const int a,const int b,const Args &...args) {return ad(ad(a,b),args...);}
template<class ...Args>il int mul(const int a,const int b,const Args &...args) {return mul(mul(a,b),args...);}
}
using namespace Modulo;
namespace Miracle{
const int N=+;
const int G=;
const int GI=;
int n,T;
int L[N];
struct Poly{
vector<int>f;
Poly(){f.clear();}
il int &operator[](const int &x){assert(x<f.size());return f[x];}
il void resize(int n){f.resize(n);}
il int size(){return f.size();}
il void clear(){f.clear();}
il void out(){for(reg i=;i<(int)f.size();++i) ot(f[i]);putchar('\n');}
}f;
int rev[*N];
int init(int n){
int m=;
for(m=;m<n;m<<=);
for(reg i=;i<m;++i){
rev[i]=(rev[i>>]>>)|((i&)?m>>:);
}
return m;
}
void NTT(Poly &f,int c){
int n=f.size();
for(reg i=;i<n;++i){
if(i<rev[i]) swap(f[i],f[rev[i]]);
}
for(reg p=;p<=n;p<<=){
int gen;
if(c==) gen=qm(G,(mod-)/p);
else gen=qm(GI,(mod-)/p);
for(reg l=;l<n;l+=p){
int buf=;
for(reg i=l;i<l+p/;++i){
int tmp=mul(f[i+p/],buf);
f[i+p/]=ad(f[i],mod-tmp);
f[i]=ad(f[i],tmp);
buf=mul(buf,gen);
}
}
}
if(c==-){
int iv=qm(n);
for(reg i=;i<n;++i){
f[i]=mul(f[i],iv);
}
}
}
il Poly operator *(Poly F,Poly G){
int n=init(F.size()+G.size()-);
F.resize(n);G.resize(n);
NTT(F,);NTT(G,);
for(reg i=;i<n;++i) F[i]=mul(F[i],G[i]);
NTT(F,-);
return F;
}
void divi(int l,int r){ if(l==&&r==){
f[]=;f[]=;return;
}
if(l==r){
f[l]=ad(f[l],mod-mul(f[],f[l-],l-));
f[l]=ad(f[l],mul(l-,f[l-]));
return;
}
int mid=(l+r)>>;
divi(l,mid);
// cout<<" divi ---------------------------"<<l<<" "<<r<<endl;
Poly F,G,K;
if(l==){
// goto s;
// cout<<"sol1---- "<<endl;
F.resize(mid+);
G.resize(mid+);
for(reg i=;i<=mid;++i){
F[i]=f[i];
G[i]=mul(f[i],i-);
}
// F.out();
// G.out();
// cout<<"hahahaha "<<endl;
F=F*G;
// F.out(); for(reg i=mid+;i<=r;++i){
f[i]=ad(f[i],F[i]);
}
// cout<<" over "<<endl;
}else{ // cout<<"sol2**** "<<endl;
F.resize(mid-l+);
G.resize(r-l+);
for(reg i=;i<=mid-l;++i){
F[i]=f[i+l];
}
for(reg i=;i<=r-l;++i){
G[i]=mul(f[i],i-);
}
// F.out();
// G.out();
// cout<<" mul "<<endl;
K=F*G;
// cout<<" K "<<endl;
// K.out(); for(reg i=mid+;i<=r;++i){
f[i]=ad(f[i],K[i-l]);
} F.clear();G.clear();
F.resize(mid-l+);G.resize(r-l+); // cout<<F.size()<<" len "<<mid-l+1<<endl;
for(reg i=;i<=mid-l;++i){
F[i]=mul(f[i+l],i+l-);
}
// cout<<" OK ? "<<endl;
for(reg i=;i<=r-l;++i){
G[i]=f[i];
} K=F*G;
for(reg i=mid+;i<=r;++i){
f[i]=ad(f[i],K[i-l]);
}
}
// s:;
// cout<<" end "<<f[3]<<endl;
divi(mid+,r);
}
int sta[N],top;
int main(){
rd(T);rd(n);
int m=init(n+);
f.resize(m); divi(,m-);
// f.out(); while(T--){
for(reg i=;i<=n;++i) rd(L[i]);
top=;
if(L[n]!=n) {
puts("");continue;
}
int ans=;
bool fl=true;
for(reg i=;i<=n;++i){
int son=;
while(top&&sta[top]-L[sta[top]]+>=i-L[i]+) ++son,--top;
// cout<<" ii "<<i<<" son "<<son<<endl;
if(top){
if(sta[top]>=i-L[i]+) fl=false;
}
sta[++top]=i;
ans=mul(ans,f[son]);
}
if(!fl) ans=;
printf("%d\n",ans);
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
*/

树形结构!

然后递归为子问题。

递归为子问题,把。。。看成。。。。

本质就是“缩点”找相似结构。或者归纳

[CTSC2018]青蕈领主的更多相关文章

  1. 并不对劲的bzoj5342:loj2554:uoj401:p4566: [Ctsc2018]青蕈领主

    题目大意 \(T\)(\(T\leq100\))组询问 有\(1\)到\(n\)(\(n\leq50000\))这\(n\)个整数组成的一个排列 定义这个排列的一个子区间是"连续" ...

  2. Loj #2554. 「CTSC2018」青蕈领主

    Loj #2554. 「CTSC2018」青蕈领主 题目描述 "也许,我的生命也已经如同风中残烛了吧."小绿如是说. 小绿同学因为微积分这门课,对"连续"这一概 ...

  3. uoj#401. 【CTSC2018】青蕈领主(分治FFT)

    传送门 话说分治\(FFT\)是个啥子啊--还有题目里那字好像念(蕈xùn) 首先考虑无解的情况:区间相交或者\(L_n\neq n\) 这两个都可以感性理解一下 所以区间之间只会有包含关系,我们把每 ...

  4. bzoj5342 CTSC2018 Day1T3 青蕈领主

    首先显然的是,题中所给出的n个区间要么互相包含,要么相离,否则一定不合法. 然后我们可以对于直接包含的关系建出一棵树,于是现在的问题就是给n个节点分配权值,使其去掉最后一个点后不存在非平凡(长度大于1 ...

  5. UOJ#401. 【CTSC2018】青蕈领主 分治,FFT

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ401.html 题解 首先,对于一个排列,它的连续段一定只有包含关系,没有相交关系. 我们可以据此得到一棵表示连续段的树. ...

  6. LOJ 2554 「CTSC2018」青蕈领主——结论(思路)+分治FFT

    题目:https://loj.ac/problem/2554 一个“连续”的区间必然是一个排列.所有 r 不同的.len 最长的“连续”区间只有包含.相离,不会相交,不然整个是一个“连续”区间. 只有 ...

  7. CTSC2018 & APIO2018 颓废 + 打铁记

    CTSC2018 & APIO2018 颓废 + 打铁记 CTSC 5 月 6 日 完美错过报道,到酒店领了房卡放完行李后直接奔向八十中拿胸牌.饭票和资料.试机时是九省联考的题,从来没做过,我 ...

  8. [冬令营模拟]GTSG2018

    上学期没有去 GTSG,于是今天老师让我们来做一下 GTSG2018 Day1 & Day3 Day1 在上午当成一场考试来搞了,Day3 由于锅太多而且 T3 玄学而被放到下午自学... 上 ...

  9. GOOD BYE OI

    大米饼正式退役了,OI给我带来很多东西 我会的数学知识基本都在下面了 博客园的评论区问题如果我看到了应该是会尽力回答的... 这也是我作为一个OIer最后一次讲课的讲稿 20190731 多项式乘法 ...

随机推荐

  1. 2018-11-24-C#-7.0

    title author date CreateTime categories C# 7.0 lindexi 2018-11-24 16:32:58 +0800 2018-2-13 17:23:3 + ...

  2. 获取文件或目录的属性 stat 函数

    头文件:  <sys/types.h>   <sys/stat.h>   <unistd.h> int stat(const char *path, struct ...

  3. 18_ShadowWalker

    白皮书中 page-fault error code: shadowWalker 原理: 接管 指定程序 的 执行页面异常.读写页面异常:然后 调用一下正常的 使其出现在快表:然后恢复到假的pte - ...

  4. 从零开始搭搭建系统3.1——顶级pom制定

    从零开始搭搭建系统3.1——顶级pom制定

  5. 防HTTP慢速攻击的nginx安全配置

    概述   慢速攻击,是一种ddos攻击的变体版本.通常来说,它通过向服务器发送正常的请求,只不过请求的头或者请求体的内容特别长,发送速度有特别慢,这样每一个连接占用的时间就会变得特别长,攻击者会在短时 ...

  6. MongoDB启动时遇到的问题

    问题一:child process failed, exited with error number 100 原因分析:100是锁了 解决办法:#cd  /usr/local/mongodb/data ...

  7. on windows in superset sql lab error "module object has no attribute sigalrm"

    改下  utils.py   文件 It works after doing the following change (sorry for the massed up alignment, prob ...

  8. django简单实现短url

    一.短url的原理 什么是短url: 简单讲就是把普通正常访问的网址,转换成比较短的网址,例如:https://www.cnblogs.com/angelyan/articles/10667354.h ...

  9. NX二次开发-获取尺寸的附加文本UF_DRF_ask_appended_text

    #include <uf.h> #include <uf_drf.h> #include <uf_obj.h> #include <uf_part.h> ...

  10. 秦曾昌人工智能课程---7、决策树集成学习Tree Ensembles

    秦曾昌人工智能课程---7.决策树集成学习Tree Ensembles 一.总结 一句话总结: 其实机器模型减少variance的比较好的方式就是 多个模型取平均值 1.CART是什么? classi ...