题目大意

  zjt 是个神仙。

  一天,zjt 正在和 yww 玩猜数游戏。

  zjt 先想一个 \([1,n]\) 之间的整数 \(x\),然后 yww 开始向他问问题。

  yww 每次给 zjt 一个区间 \([l,r](1\leq l\leq r\leq n)\),并询问:\(x\) 是否在区间 \([l,r]\) 内?

  对于 NOIP 爆零的 yww 来说,他只会用二分法去猜出这个数。

  但是 zjt 决定加大难度。他只会在 yww 给出所有想问的问题之后一次性给出答案。

  请你帮助 yww 算出,有多少种可能的区间的集合 \(S\),满足 yww 在询问所有 \(S\) 中的区间的情况下,无论 \(x\) 是多少,yww 都能猜出来。

  方案数对 \(p\) 取模。

  \(n\leq 300,p<2^{30}\)

题解

  考虑求出不满足要求的集合个数。

  对于一个集合 \(S\),求出每一个数被那些区间覆盖了,记为 \(S_i\)。然后给每个数一个编号 \(a_i\),满足 \(S_i\) 相同的数 \(a_i\) 相同。

  对于两个位置 \(a_i=a_j\),如果一个区间覆盖了 \(i\),那么这个区间就一定覆盖了 \(j\)。

  每次把 \(a\) 中的第一个数 \(x\) 放入 \(b\) 的末尾,然后在 \(a\) 中删掉最后一个 \(x\) 前的所有数(包括最后一个 \(x\))。

  例如 \(a=[1,2,3,2,4,2,5,5,10,6,7,8,7,6,9]\)

  此时 \(b=[1,2,5,10,6,9]\)

  可以发现,如果把 yww 给出的没有包含任何数的区间删掉,那么剩下的区间对应着一个长度为 \(\lvert b\rvert\) 的序列的答案。

  而且被删掉的区间是否存在都没有影响。

  这样就可以DP了。

  记 \(f_i\) 为 \(i\) 个数的答案,\(g_{i,j}\) 为 \(i\) 个数,处理之后之剩 \(j\) 个数的答案。

  那么

\[f_i=2^{\binom{i+1}{2}}-\sum_{j=1}^{i-1}f_jg_{i,j}\\
g_{i,j}=g_{i-1,j-1}+\sum_{k=0}g_{i-k-2,j-1}2^{\binom{k+1}{2}}
\]

  时间复杂度:\(O(n^3)\) 或 \(O(n^2\log n)\)

  记 \(F(x)=\sum_{i\geq 0}f_ix^i,G_i(x)=\sum_{j\geq 0}g_{j,i}x^j,H(x)=\sum_{i\geq 0}2^{\binom{i+1}{2}}x^i,A(x)=x+\sum_{i\geq 2}\binom{i-1}{2}x^i\)

  记 \(A^{-1}(x)\) 为 \(A(x)\) 的复合逆:\(A(A^{-1}(x))=x\)

\[G_i(x)=A(x)^i\\
\sum_{j=1}^if_jg_{i,j}=h_i\\
F(A(x))=H(x)\\
F(x)=H(A^{-1}(x))
\]

  然后直接扩展拉格朗日反演求一项的值就好了。

\[[x^n]H(A^{-1}(x))=[x^{-1}](\frac{1}{n}\frac{dH(x)}{dx}\frac{1}{A(x)^n})
\]

  时间复杂度:\(O(n\log n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const int N=510;
int n;
ll p;
ll pw[N*N];
ll f[N];
ll g[N][N];
void init()
{
pw[0]=1;
for(int i=1;i<=n*n;i++)
pw[i]=pw[i-1]*2%p;
}
int main()
{
open("guess");
scanf("%d%lld",&n,&p);
init();
g[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
{
g[i][j]=g[i-1][j-1];
for(int k=0;i-2-k>=j-1;k++)
g[i][j]=(g[i][j]+g[i-2-k][j-1]*pw[k*(k+1)/2])%p;
}
for(int i=1;i<=n;i++)
{
f[i]=pw[i*(i+1)/2];
for(int j=1;j<i;j++)
f[i]=(f[i]-f[j]*g[i][j])%p;
}
ll ans=f[n];
ans=(ans%p+p)%p;
printf("%lld\n",ans);
return 0;
}

【CSA35G】【XSY3318】Counting Quests DP 拉格朗日反演 NTT的更多相关文章

  1. [拉格朗日反演][FFT][NTT][多项式大全]详解

    1.多项式的两种表示法 1.系数表示法 我们最常用的多项式表示法就是系数表示法,一个次数界为\(n\)的多项式\(S(x)\)可以用一个向量\(s=(s_0,s_1,s_2,\cdots,s_n-1) ...

  2. 【XSY2843】「地底蔷薇」 NTT什么的 扩展拉格朗日反演

    题目大意 给定集合\(S\),请你求出\(n\)个点的"所有极大点双连通分量的大小都在\(S\)内"的不同简单无向连通图的个数对\(998244353\)取模的结果. \(n\le ...

  3. BZOJ 3684: 大朋友和多叉树 [拉格朗日反演 多项式k次幂 生成函数]

    3684: 大朋友和多叉树 题意: 求有n个叶子结点,非叶节点的孩子数量\(\in S, a \notin S\)的有根树个数,无标号,孩子有序. 鏼鏼鏼! 树的OGF:\(T(x) = \sum_{ ...

  4. 【bzoj3684】 大朋友和多叉树 生成函数+多项式快速幂+拉格朗日反演

    这题一看就觉得是生成函数的题... 我们不妨去推下此题的生成函数,设生成函数为$F(x)$,则$[x^s]F(x)$即为答案. 根据题意,我们得到 $F(x)=x+\sum_{i∈D} F^i(x)$ ...

  5. loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)

    题面 传送门 题解 肝了一个下午--我老是忘了拉格朗日反演计算的时候多项式要除以一个\(x\)--结果看它推倒简直一脸懵逼-- 做这题首先你得知道拉格朗日反演是个什么东西->这里 请坐稳,接下来 ...

  6. bzoj3684: 大朋友和多叉树(拉格朗日反演+多项式全家桶)

    题面 传送门 题解 首先你得知道什么是拉格朗日反演->这里 我们列出树的个数的生成函数 \[T(x)=x+\prod_{i\in D}T^i(x)\] \[T(x)-\prod_{i\in D} ...

  7. [BZOJ3684][拉格朗日反演+多项式求幂]大朋友和多叉树

    题面 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为\(1\)的结点是叶子结 ...

  8. 【BZOJ3684】大朋友和多叉树(拉格朗日反演)

    题目链接 题意 求满足如下条件的多叉树个数: 1.每一个点的儿子个数在给定的集合 \(S\) 内 2.总的叶子节点树为 \(s\) 儿子之间有顺序关系,但节点是没有标号的. Sol 拉格朗日反演板子题 ...

  9. 洛谷 P5206 - [WC2019]数树(集合反演+NTT)

    洛谷题面传送门 神仙多项式+组合数学题,不过还是被我自己想出来了( 首先对于两棵树 \(E_1,E_2\) 而言,为它们填上 \(1\sim y\) 使其合法的方案数显然是 \(y\) 的 \(E_1 ...

随机推荐

  1. CentOS 7.4 下 如何部署 AspNetCore 结合 consul

    上篇我们讲到consul的概念,以及在WIN下如何使用:http://www.cnblogs.com/szlblog/p/9162557.html 步骤如下: 1.安装虚拟机VM 2.下载安装 Cen ...

  2. 使用wepy开发微信小程序01——常用的组件

    1.axio.js 'use strict' import axios from 'axios' import wepyAxiosAdapter from 'wepy-plugin-axios/dis ...

  3. 15个常用的javaScript正则表达式

    1 用户名正则 //用户名正则,4到16位(字母,数字,下划线,减号) ,}$/; //输出 true console.log(uPattern.test("iFat3")); 2 ...

  4. 《JavaScript高级程序设计》笔记:面向对象的程序设计(六)

    面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象. 理解对象 创建自定义对象的最简单的方法就是创建一个Object的实例,然后再为它添加属性和方法.例 ...

  5. CentOS7 firewalld 打开关闭端口

    1. firewalld的基本使用 启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status ...

  6. (四) Keras Dropout和正则化的使用

    视频学习来源 https://www.bilibili.com/video/av40787141?from=search&seid=17003307842787199553 笔记 使用drop ...

  7. HTML导出excel

    在博客园找到的相关问题http://q.cnblogs.com/q/12952  还有相关的回答http://www.cnblogs.com/zhouxin/archive/2009/12/11/16 ...

  8. HDU 6152 - Friend-Graph

    Friend-Graph Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. Orchard克死你 之 刚起步

    从去年开始,一直想琢磨一个比较灵活的.Net框架用,经一个月的地毯式搜寻,把目标定位到2009年的微软开源项目Orchard,虽然起步甚晚,但对我们这些菜鸟,仍旧是有可学习之处,所以打算花大半年时间想 ...

  10. mysql 高级

    Sql优化: 1.SELECT语句中避免使用 *, 尽量根据业务需求按字段进行查询 举例:如果表中有个字段用的是clob或者是blob这种大数据字段的话, 他们的查询应该根据业务需要来进行指定字段的查 ...