【CF960G】Bandit Blues

题面

洛谷

题解

思路和这道题一模一样,这里仅仅阐述优化的方法。

看看答案是什么:

\[Ans=C(a+b-2,a-1)\centerdot s(n-1,a+b-2)
\]

组合数我们已经可以\(O(N)\)求了,主要是第一类斯特林数存在问题。

考虑它的转移:

\[s(n,m)=s(n-1,m-1)+(n-1)*s(n-1,m)
\]

根据这个转移,我们写出它\(n\)固定时的生成函数

\[G(x)=\prod_{i=0}^{n-1}(x+i)
\]

然后每一个\(s(n,m)\)就是升序第\(m\)项的次数。

为什么生成函数是这个?

引用\(yyb\)的:

把\(n\)为定值时的所有的第一类斯特林数按照\(n\)分类分成行,发现每次的\(s(n,m)\)转移必定要从\(n−1\)行转移过来,而每次转移都是\(m−1\)变到\(m\),系数为\(1\),因此有一项\(x\),同理有一项\(n−1\),因此就可以得到上面的那个生成函数。

然后对于这个东西我们用分治+\(NTT\)就可以\(O(n\log^2)\)地做了。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int Mod = 998244353;
int fpow(int x, int y) {
int res = 1;
while (y) {
if (y & 1) res = 1ll * res * x % Mod;
y >>= 1;
x = 1ll * x * x % Mod;
}
return res;
}
const int G = 3, iG = fpow(G, Mod - 2);
const int MAX_N = 3e5 + 5;
int rev[MAX_N], Limit;
void NTT(vector<int> &p, int op) {
for (int i = 0; i < Limit; i++) if (i < rev[i]) swap(p[i], p[rev[i]]);
for (int i = 1; i < Limit; i <<= 1) {
int rot = fpow(op == 1 ? G : iG, (Mod - 1) / (i << 1));
for (int j = 0; j < Limit; j += (i << 1)) {
int w = 1;
for (int k = 0; k < i; k++, w = 1ll * w * rot % Mod) {
int x = p[j + k], y = 1ll * w * p[i + j + k] % Mod;
p[j + k] = (x + y) % Mod, p[i + j + k] = (x - y + Mod) % Mod;
}
}
}
if (op == -1) {
int inv = fpow(Limit, Mod - 2);
for (int i = 0; i < Limit; i++) p[i] = 1ll * inv * p[i] % Mod;
}
} vector<int> mul(vector<int> &A, vector<int> &B) {
static vector<int> C;
C.clear();
int p = 0, sz = A.size() + B.size() - 2;
for (Limit = 1; Limit <= sz + 1; Limit <<= 1, ++p);
for (int i = 0; i < Limit; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (p - 1));
A.resize(Limit), B.resize(Limit);
NTT(A, 1), NTT(B, 1);
for (int i = 0; i < Limit; i++) C.push_back(1ll * A[i] * B[i] % Mod);
NTT(C, -1);
return C;
}
vector<int> Div(int l, int r) {
vector<int> L, R;
if (l == r) return {l, 1};
int mid = (l + r) >> 1;
L = Div(l, mid), R = Div(mid + 1, r);
return mul(L, R);
}
int fac(int x) { int res = 1; for (int i = 1; i <= x; i++) res = 1ll * res * i % Mod; return res; }
int C(int n, int m) {
if (m > n) return 0;
else return 1ll * fac(n) * fpow(fac(m), Mod - 2) % Mod * fpow(fac(n - m), Mod - 2) % Mod;
}
vector<int> Ans;
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
int N, A, B;
cin >> N >> A >> B;
if (!A || !B || A + B - 2 > N - 1) return puts("0") & 0;
if (N == 1) return puts("1") & 0;
Ans = Div(0, N - 2);
printf("%d\n", (int)(1ll * Ans[A + B - 2] * C(A + B - 2, A - 1) % Mod));
return 0;
}

【CF960G】Bandit Blues的更多相关文章

  1. 【CF960G】Bandit Blues(第一类斯特林数,FFT)

    [CF960G]Bandit Blues(第一类斯特林数,FFT) 题面 洛谷 CF 求前缀最大值有\(a\)个,后缀最大值有\(b\)个的长度为\(n\)的排列个数. 题解 完完全全就是[FJOI] ...

  2. 【cf960G】G. Bandit Blues(第一类斯特林数)

    传送门 题意: 现在有一个人分别从\(1,n\)两点出发,包中有一个物品价值一开始为\(0\),每遇到一个价值比包中物品高的就交换两个物品. 现在已知这个人从左边出发交换了\(a\)次,从右边出发交换 ...

  3. Luogu P4609 [FJOI2016]建筑师&&CF 960G Bandit Blues

    考虑转化题意,我们发现其实就是找一个长度为\(n\)的全排列,使得这个排列有\(A\)个前缀最大值,\(B\)个后缀最大值,求方案数 我们考虑把最大值拎出来单独考虑,同时定义一些数的顺序排列为单调块( ...

  4. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  5. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  6. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  7. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  8. 【调侃】IOC前世今生

    前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...

  9. Python高手之路【三】python基础之函数

    基本数据类型补充: set 是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object ...

随机推荐

  1. c++ 派生类的构造函数次序

    #include <iostream> using namespace std; class CFatherSum //父类Sum { public: CFatherSum(int iRe ...

  2. Input and Output-The input is all the sources of action for your app

    Programs take input and produce output. The output is the result of doing something with the input. ...

  3. BZOJ1049:[HAOI2006]数字序列(DP)

    Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列. 但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个 ...

  4. 3、Spring Cloud - Eureka(构建服务端/客户端)

    3.1.Eureka简介 3.1.1.什么是 Eureka 和Consul.Zookeeper 类似, Eureka 是一个用于服务注册和发现的组件,最开始主要应用 于亚马逊公司旗下的云计算服务平台 ...

  5. MVC5新特性(一)之RouteAttribute打造自己的URL规则

    1.RouteAttribute概述 RouteAttribute的命名空间是System.Web.Mvc,区别与web api的RouteAttribute(它的命名空间是System.Web.Ht ...

  6. 机器学习基石笔记:Homework #2 decision stump相关习题

    原文地址:http://www.jianshu.com/p/4bc01760ac20 问题描述 程序实现 17-18 # coding: utf-8 import numpy as np import ...

  7. 算法——(4)哈希、hashmap、hashtable

    1. Hash 把任意长度的输入通过散列算法,变换成固定长度的输出,该输出就是散列值.拥有四个特性: 1. 拥有无限的输入域和固定大小的输出域 2. 如果输入值相同,返回值一样 3. 如果输入值不相同 ...

  8. QTP基本方法3-----截屏

    1.桌面截屏 Desktop.captureBitMap  path[,bolean] path:保存路径,可选择绝对路径或相对路径 相对路径是保存在脚本保存的目录下编号最大的res目录下. bole ...

  9. WPF实战俄罗斯方块

    概述 本文试图通过经典的游戏-俄罗斯方块,来演示WPF强大的图形界面编程功能. 涉及的图形方面有这几个方面: 1.不规则界面的设置 2.布局系统的使用 3.2D图形的应用 4.输入事件的响应 5.风格 ...

  10. ASP.Net GridView 基础 Template模板

    一.了解Template AlternatingItemTemplate定义交替行的内容和外观,如果没有规定模板,则使用ItemTemplate:EditItemTemplate定义当前正在编辑的行的 ...