题面1 题面2

两个题推导是一样的,具体实现不一样,所以写一起了,以FJOI 2016 建筑师 的题面为标准

前后在组合意义下一样,现在只考虑前面,可以发现看到的这a个建筑将这一段划分成了a-1个区间,区间里的数随意填。

看起来可以用组合数算,但是还要考虑看到的建筑,所以我们把每个建筑和它后面这段区间合起来看。设区间的长度是len,这就是一个len+1个数的圆排列(等于len!,相当于固定一个开头后面随便排)

这样考虑前后就是将n-1个数划分为a+b-2个全排列,n-1是因为最高的那个在两边都没被算进去,是第一类斯特林数。同时a+b-2个圆排列之间还要选出来a-1个放前面,乘上组合数即可。现在关键是如何求第一类斯特林数。

FJOI那道题n*k不是很大,可以直接$O(nk)$递推,边界条件是$S[0][0]=1$,转移是$S[i][j]=S[i-1][j-1]+S[i-1][j]*(i-1)$

CF那道题只有一次询问,但是n,k都很大,我们考虑第一类斯特林数在第一维固定下的生成函数:$G(x)=\prod\limits_{i=0}^{n-1}(x+i)$,x是从$s[i-1][j-1]$来的,i-1是从$s[i-1][j]*(i-1)$来的。用分治NTT优化

Code1

 //Simple NTT
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define vint vector<int>
using namespace std;
const int N=,mod=;
int fac[N],inv[N],rev[N];
int aa[N],bb[N],pw[][];
int a,b,n,l1,l2,G,Gi,Ni; vint stl;
int Qpow(int x,int k)
{
if(k==) return x;
int tmp=Qpow(x,k/);
return k%?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
}
int C(int a,int b)
{
return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void SPJ()
{
if(!a||!b||n-<a+b-) printf(""),exit();
if(n==) printf(""),exit();
}
void Pre()
{
fac[]=inv[]=,G=,Gi=Qpow(G,mod-);
for(int i=;i<=;i++)
{
pw[i][]=Qpow(G,(mod-)/(<<i));
pw[i][]=Qpow(Gi,(mod-)/(<<i));
}
for(int i=;i<=a+b;i++) fac[i]=1ll*fac[i-]*i%mod;
inv[a+b]=Qpow(fac[a+b],mod-);
for(int i=a+b-;i;i--) inv[i]=1ll*inv[i+]*(i+)%mod;
}
void Prework(vint &a,vint &b)
{
register int i;
l1=a.size()-,l2=b.size()-;
l1+=l2,l2=; while(l2<=l1) l2<<=;
a.resize(l2),b.resize(l2);
for(i=;i<=l2;i++) aa[i]=a[i];
for(i=;i<=l2;i++) bb[i]=b[i];
for(i=;i<l2;i++)
rev[i]=(rev[i>>]>>)+(i&)*(l2>>);
}
void Trans(int *arr,int len,int typ)
{
register int i,j,k;
for(i=;i<len;i++)
if(rev[i]>i) swap(arr[rev[i]],arr[i]);
for(i=;i<=len;i<<=)
{
int lth=i>>,ort=pw[(int)log2(i)][typ==-];
for(j=;j<len;j+=i)
{
int ori=,tmp;
for(k=j;k<j+lth;k++,ori=1ll*ori*ort%mod)
{
tmp=1ll*ori*arr[k+lth]%mod;
arr[k+lth]=(arr[k]-tmp+mod)%mod;
arr[k]=(arr[k]+tmp)%mod;
}
}
}
if(typ==-)
{
int Ni=Qpow(len,mod-);
for(i=;i<=len;i++)
arr[i]=1ll*arr[i]*Ni%mod;
}
}
vint NTT(vint a,vint b)
{
Prework(a,b);
Trans(aa,l2,),Trans(bb,l2,);
for(int i=;i<l2;i++) aa[i]=1ll*aa[i]*bb[i]%mod;
Trans(aa,l2,-);
vint ret; ret.clear();
for(int i=;i<l2;i++) ret.push_back(aa[i]);
return ret;
}
vint CDQ(int l,int r)
{
if(l==r) return {l,};
else
{
int mid=(l+r)/;
vint a1=CDQ(l,mid),a2=CDQ(mid+,r);
return NTT(a1,a2);
}
}
int main()
{
scanf("%d%d%d",&n,&a,&b);
SPJ(),Pre(),stl=CDQ(,n-);
printf("%d",1ll*C(a+b-,a-)*stl[a+b-]%mod);
return ;
}

Code2

 #include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,M=,mod=1e9+;
int fac[N],inv[N],S[N][M];
int a,b,n,T,l1,l2,G,Gi,Ni;
int Qpow(int x,int k)
{
if(k==) return x;
int tmp=Qpow(x,k/);
return k%?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
}
int C(int a,int b)
{
return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;
}
bool SPJ()
{
if(!a||!b||n-<a+b-)
{puts(""); return false;}
if(n==)
{puts(""); return false;}
return true;
}
void Pre()
{
register int i,j;
fac[]=inv[]=,S[][]=;
for(i=;i<=;i++) fac[i]=1ll*fac[i-]*i%mod;
inv[]=Qpow(fac[],mod-);
for(i=;i;i--) inv[i]=1ll*inv[i+]*(i+)%mod;
for(i=;i<=;i++)
for(j=;j<=;j++)
S[i][j]=(S[i-][j-]+1ll*(i-)*S[i-][j]%mod)%mod;
}
int main()
{
Pre();
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&a,&b);
if(SPJ()) printf("%lld\n",1ll*C(a+b-,a-)*S[n-][a+b-]%mod);
}
return ;
}

解题:CF960G Bandit Blues & FJOI 2016 建筑师的更多相关文章

  1. CF960G Bandit Blues 第一类斯特林数、NTT、分治/倍增

    传送门 弱化版:FJOI2016 建筑师 由上面一题得到我们需要求的是\(\begin{bmatrix} N - 1 \\ A + B - 2 \end{bmatrix} \times \binom ...

  2. CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】

    题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...

  3. [CF960G] Bandit Blues

    题意 给你三个正整数 \(n,a,b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大值的数的个数,求长度为 \(n\) 的排列中满足 \(A = a ...

  4. CF960G Bandit Blues 分治+NTT(第一类斯特林数)

    $ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...

  5. CF960G Bandit Blues(第一类斯特林数)

    传送门 可以去看看litble巨巨关于第一类斯特林数的总结 设\(f(i,j)\)为\(i\)个数的排列中有\(j\)个数是前缀最大数的方案数,枚举最小的数的位置,则有递推式\(f(i,j)=f(i- ...

  6. [CF960G]Bandit Blues(第一类斯特林数+分治卷积)

    Solution: ​ 先考虑前缀,设 \(f(i, j)\) 为长度为 \(i\) 的排列中满足前缀最大值为自己的数有 \(j\) 个的排列数. 假设新加一个数 \(i+1\) 那么会有: \[ f ...

  7. CF960G Bandit Blues 第一类斯特林数+分治+FFT

    题目传送门 https://codeforces.com/contest/960/problem/G 题解 首先整个排列的最大值一定是 \(A\) 个前缀最大值的最后一个,也是 \(B\) 个后缀最大 ...

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

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

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

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

随机推荐

  1. # 2017-2018-2 20155319『网络对抗技术』Exp5:MSF基础应用

    2017-2018-2 20155319『网络对抗技术』Exp5:MSF基础应用 基础问题回答 用自己的话解释什么是exploit,payload,encode exploit:使用者利用漏洞进行攻击 ...

  2. 20155334 《网络攻防》 Exp7 网络欺诈防范

    20155334 <网络攻防> Exp7 网络欺诈防范 一.基础问题回答 通常在什么场景下容易受到DNS spoof攻击 同一局域网下,以及各种公共网络. 在日常生活工作中如何防范以上两攻 ...

  3. MFC 用ShellExecute打开外部文件

    知识点: 获取CListCtrl选中文本 用ShellExecute打开外部文件 一.CListCtrl::GetFirstSelectedItemPosition CListCtrl::GetFir ...

  4. P问题,NP问题,NPC问题,NP-hard问题

    1.P问题:一个问题能找到一个在多项式时间里解决他的算法 多项式时间(o(1),o(lgn),o(n的a次方)) 非多项式时间 o(a的n次方)  o(n!) 2.NP问题:在多项式时间找不到问题的解 ...

  5. springboot打包成war后部署项目出现异常 LifecycleException: Failed to start component

    完整异常:org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].Sta ...

  6. bootstrap-validator基本使用(自定义验证身份证号和手机号)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  7. ElasticSearch入门 第九篇:实现正则表达式查询的思路

    这是ElasticSearch 2.4 版本系列的第九篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  8. java算法面试题

    前言:线上面试题与大家分享,并记录求职道路的酸甜苦辣,特此留念. 李雷和韩梅梅坐前后排,上课想说话怕被老师发现,所以改为传小纸条.为了不被老师发现他们纸条上说的是啥,他们约定了如下方法传递信息:将26 ...

  9. 金蝶盘点机PDA仓库条码管理家电类序列号扫描操作方法-采购入库单

    1.1.  采购入库单 传统的进销存管理软件需要人工识别商品品种,清点商品数量,然后再去人工手工在电脑上一行行的录入采购入库单.录单效率低,误差大. 如果使用汉码盘点机PDA,入库时,仓管员只需要手持 ...

  10. 5分钟让你明白HTTP协议

    一.HTTP简介 1.http协议介绍 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标 ...