CF960G
首先我们考虑$n$的情况,显然以$n$为分界线可以将整个序列分成两部分,就像这样:
、
那么我们考虑:在这个东西前面才会有前缀最大的统计,在这个东西后面才会有后缀最大的统计
这样就剩下了$n-1$个元素,而我们需要把这$n-1$个元素分成$A+B-2$个集合,然后把每个集合的最大的一个放在一端,然后剩余部分全排列
设一个集合中有$k$个元素,那么剩余元素全排列的方案数就是$(k-1)!$
考虑这也是对$k$个元素放在一个圆排列上的方案数,因此我们能搞出一个第一类斯特林数的表达式:
$S_{1}(n-1,A+B-2)$
然后考虑这几个集合在左右的分布,有:$C_{A+B-2}^{A-1}$
因此最终答案即为$S_{1}(n-1,A+B-2)C_{A+B-2}^{A-1}$
然后第一类斯特林数可以倍增$O(nlog_{2}n)$求解,因此能通过这题:
- // luogu-judger-enable-o2
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <algorithm>
- #define ll unsigned long long
- #define uint unsigned int
- using namespace std;
- const uint mode=998244353;
- uint pow_mul(uint x,uint y)
- {
- uint ret=1;
- while(y)
- {
- if(y&1)ret=1ll*ret*x%mode;
- x=1ll*x*x%mode,y>>=1;
- }
- return ret;
- }
- uint inv[300005],minv[300005],mul[300005];
- void init()
- {
- inv[0]=inv[1]=minv[0]=minv[1]=mul[0]=mul[1]=1;
- for(uint i=2;i<=300000;i++)
- {
- inv[i]=1ll*(mode-mode/i)*inv[mode%i]%mode;
- minv[i]=1ll*minv[i-1]*inv[i]%mode;
- mul[i]=1ll*mul[i-1]*i%mode;
- }
- }
- uint MOD(uint x,uint y)
- {
- return x+y>=mode?x+y-mode:x+y;
- }
- uint to[(1<<20)+5];
- uint n,a,b;
- void NTT(uint *a,uint len,int k)
- {
- for(uint i=0;i<len;i++)if(i<to[i])swap(a[i],a[to[i]]);
- for(uint i=1;i<len;i<<=1)
- {
- uint w0=pow_mul(3,(mode-1)/(i<<1));
- for(uint j=0;j<len;j+=(i<<1))
- {
- uint w=1;
- for(uint o=0;o<i;o++,w=1ll*w*w0%mode)
- {
- ll w1=a[j+o],w2=1ll*a[j+o+i]*w%mode;
- a[j+o]=MOD(w1,w2)%mode,a[j+o+i]=MOD(mode-w2,w1);
- }
- }
- }
- if(k==-1)
- {
- uint inv=pow_mul(len,mode-2);
- for(uint i=1;i<(len>>1);i++)swap(a[i],a[len-i]);
- for(uint i=0;i<len;i++)a[i]=1ll*a[i]*inv%mode;
- }
- }
- uint A[(1<<20)+5],B[(1<<20)+5],C[(1<<20)+5];
- uint tempt[(1<<20)+5],tempf[(1<<20)+5],tempg[(1<<20)+5],tempG[(1<<20)+5],tempF[(1<<20)+5];
- uint ret[(1<<20)+5];
- void mult(uint *f,uint *g,uint len)
- {
- uint lim=1,l=0;
- while(lim<=2*(len+1))lim<<=1,l++;
- for(uint i=0;i<lim;i++)to[i]=((to[i>>1]>>1)|((i&1)<<(l-1)));
- for(uint i=0;i<lim;i++)A[i]=B[i]=0;
- for(uint i=0;i<=len;i++)A[i]=f[i],B[i]=g[i];
- for(uint i=0;i<lim;i++)C[i]=0;
- NTT(A,lim,1),NTT(B,lim,1);
- for(uint i=0;i<lim;i++)C[i]=1ll*A[i]*B[i]%mode;
- NTT(C,lim,-1);
- }
- void solve(uint *g,uint dep)
- {
- if(!dep){g[0]=1;return;}
- if(dep==1)
- {
- g[0]=0,g[1]=1;
- return;
- }
- if(dep&1)
- {
- solve(g,dep-1);
- for(uint i=1;i<=dep;i++)tempG[i]=C[i-1];
- for(uint i=0;i<dep;i++)tempG[i]=MOD(tempG[i],1ll*C[i]*(dep-1)%mode);
- for(uint i=0;i<=dep;i++)g[i]=tempG[i];
- }else
- {
- uint mid=(dep>>1);
- solve(g,mid);
- uint temp=1;
- for(uint i=0;i<=mid;i++,temp=1ll*temp*mid%mode)tempg[i]=1ll*g[mid-i]*mul[mid-i]%mode,tempf[i]=1ll*temp*minv[i]%mode;
- mult(tempg,tempf,mid);
- for(uint i=0;i<=mid;i++)tempF[i]=1ll*C[mid-i]*minv[i]%mode;
- mult(tempF,g,mid);
- for(uint i=0;i<=dep;i++)g[i]=C[i];
- }
- }
- uint get_C(uint x,uint y)
- {
- if(x<y)return 0;
- return 1ll*mul[x]*minv[y]%mode*minv[x-y]%mode;
- }
- int main()
- {
- scanf("%u%u%u",&n,&a,&b);init();
- solve(ret,n-1);
- printf("%u\n",1ll*ret[a+b-2]*get_C(a+b-2,a-1)%mode);
- return 0;
- }
CF960G的更多相关文章
- 【CF960G】Bandit Blues(第一类斯特林数,FFT)
[CF960G]Bandit Blues(第一类斯特林数,FFT) 题面 洛谷 CF 求前缀最大值有\(a\)个,后缀最大值有\(b\)个的长度为\(n\)的排列个数. 题解 完完全全就是[FJOI] ...
- CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】
题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...
- 【CF960G】Bandit Blues
[CF960G]Bandit Blues 题面 洛谷 题解 思路和这道题一模一样,这里仅仅阐述优化的方法. 看看答案是什么: \[ Ans=C(a+b-2,a-1)\centerdot s(n-1,a ...
- CF960G(第一类斯特林数)
题目 CF960G 做法 设\(f(i,j)\)为\(i\)个数的序列,有\(j\)个前缀最大值的方案数 我们考虑每次添一个最小数,则有:\(f(i,j)=f(i-1,j)+(i-1)*f(i-1,j ...
- [CF960G] Bandit Blues
题意 给你三个正整数 \(n,a,b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大值的数的个数,求长度为 \(n\) 的排列中满足 \(A = a ...
- CF960G Bandit Blues 第一类斯特林数、NTT、分治/倍增
传送门 弱化版:FJOI2016 建筑师 由上面一题得到我们需要求的是\(\begin{bmatrix} N - 1 \\ A + B - 2 \end{bmatrix} \times \binom ...
- 解题:CF960G Bandit Blues & FJOI 2016 建筑师
题面1 题面2 两个题推导是一样的,具体实现不一样,所以写一起了,以FJOI 2016 建筑师 的题面为标准 前后在组合意义下一样,现在只考虑前面,可以发现看到的这a个建筑将这一段划分成了a-1个区间 ...
- CF960G Bandit Blues 分治+NTT(第一类斯特林数)
$ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...
- CF960G Bandit Blues(第一类斯特林数)
传送门 可以去看看litble巨巨关于第一类斯特林数的总结 设\(f(i,j)\)为\(i\)个数的排列中有\(j\)个数是前缀最大数的方案数,枚举最小的数的位置,则有递推式\(f(i,j)=f(i- ...
- 【cf960G】G. Bandit Blues(第一类斯特林数)
传送门 题意: 现在有一个人分别从\(1,n\)两点出发,包中有一个物品价值一开始为\(0\),每遇到一个价值比包中物品高的就交换两个物品. 现在已知这个人从左边出发交换了\(a\)次,从右边出发交换 ...
随机推荐
- 使用Wireshark完成实验3-IP
1.使用Wireshark打开ip-ethereal-trace-1,如图 电脑IP地址为192.168.1.102 2.如图,IP包头中上层协议字段的值为1,代表为ICMP 3.如图,IP头中有20 ...
- Java基础学习:8、构造器(构造方法)和this
一.构造器: 1.定义:构造器是类的特殊方法,它的主要作用是完成对象的初始化. 即在创建对象时初始化对象. 本质是方法. 2.特点: a.方法名和类名一致. b.无返回值. c. ...
- GNSS模块
1. Location服务注册 第一个注册是在 SystemServer 中将 location 服务注册到 ServiceManager中去:第二个注册是在 SystemServiceRegistr ...
- Linux环境下给python项目写个启停服务
写个服务,写完后放在/lib/systemd/system路径下 update_rule.server [Unit] Description = TinyScan update rule [Servi ...
- 5.mysql的explain的分析
执行分析: 1.id 含义:表示查询的子句或者操作表的顺序 三种情况:id 相同,执行的顺序由上到下: id不同,id越大优先级越高,越先执行: id相同不相同同时存在: 2.select_type ...
- Django-django-celery的配置
1.安装django-celery pip install django-celery 2.添加配置 demos/demos/settings.py(我的项目名为demos,这里只是示范,切勿搞混 ...
- Java调用Kettle
Java 调用 kettle,难的不是怎么调用,而是解决 maven 依赖冲突问题,直接将 kettle 依赖,添加到我们的 maven 工程,可能会导致代码大范围报错:解决方案也很简单,就是直接从 ...
- 国际版Office365客户端配置
Email Provider IMAP Settings POP Settings SMTP Settings Microsoft 365 Outlook Hotmail Live.com Serve ...
- EasyUI异步Tree默认请求id获取不到问题
在做淘淘商城项目过程中,在新增商品-选择类目时,使用EasyUI的异步Tree功能,根据视频教程封装了一个common pojo--EUTreeNode对象,属性值取parentId(id).text ...
- js中常用的运算符
1. ?. 链接运算符 特性: 一旦遇到空置就会终止 例子: let name = obj?.name persion.getTip?.() // 没有getTip 方法则不会执行 2. ?? 空值合 ...