[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. linux 查看服务器序列号(S/N)

    [root@node1~]# dmidecode -t 查看支持的参数 dmidecode: option requires an argument -- 't' Type number or key ...

  2. shell脚本输出九九乘法表

    #!/bin/bash#输出九九乘法表 for ((i=1;i<=9;i++)) do for ((j=1;j<=$i;j++)) do echo -n $j'x'$i=$(($i*$j) ...

  3. [牛客小白月赛18] Forsaken的数列

    FHQTreap裸题... 用文艺平衡树的方法,维护区间和然后一直Push_Down就可以了(60行代码暴力AC) //张家奇怎么又AKIOI了呀,怎么CSP也满分啊...怎么清北天天给他打电话啊.. ...

  4. delphi xe10 文件目录/路径操作 (Andorid、ios)

    //获取临时文件路径(支持安卓.IOS) function GeFileName(const AFileName: string): string; begin {$IFDEF ANDROID} Re ...

  5. Ruby 环境变量

    Ruby 环境变量 Ruby 解释器使用下列环境变量来控制它的行为.ENV 对象包含了所有当前设置的环境变量列表. 变量 描述 DLN_LIBRARY_PATH 动态加载模块搜索的路径. HOME 当 ...

  6. Delphi中任务栏状态区的编程

    在Windows桌面的任务栏上有一个凹陷的区域,其中显示着系统时钟以及一些图标,这个长方形的区域便是Windows的任务栏状态区(taskbar status area).本文将介绍使用Borland ...

  7. NX二次开发-UFUN导入表达式UF_MODL_import_exp

    最近在做表达式创建,发现UFUN的创建表达式函数UF_MODL_create_exp,UF_MODL_create_exp_tag没有办法创建字符串类型的表达式,例如AA="BB" ...

  8. NX二次开发-NXOpen中Point3d类型转换成point类型

    NX9+VS2012 #include <NXOpen/NXObject.hxx> #include <NXOpen/Part.hxx> #include <NXOpen ...

  9. 在360的兼容模式下关于innerHTML=“”,引发的问题

    innerHTML属性,可以动态设置和修改dom,但是在360的兼容模式下回存在一些问题...... var dBody = document.body; var fatherDom = docume ...

  10. 基于SpringBoot的Swagger2快速入门

    1. Springboot 集成 Swagger2 1.1 导入Swagger2 依赖 <!-- https://mvnrepository.com/artifact/io.springfox/ ...