Codeforces 题目传送门 & 洛谷题目传送门

神仙题,只不过感觉有点强行二合一(?)。

首先考虑什么样的数组 \(a\) 符合条件,我们考虑一个贪心的思想,我们从前到后遍历,对于每一个 \(a_i\) 如果它已经在前面出现了就不断给它加 \(1\) 直到它没有出现过为止。如果某个 \(a_i\) 超过了 \(n\) 则不符合条件,正确性显然。这样看起来还是有点抽象,我们不妨把它转化成这样的模型:有一架飞机有 \(n\) 个位置,有 \(n\) 个乘客要登飞机,每个乘客都预定了一个位置 \(a_i\),每个乘客上飞机的时候,如果它的位置已经被占了,那么它会一直向前走直到到达一个空位为止并坐下,如果有乘客没位置坐则不符合题意。

这是一个非常经典的问题,仿照那题的解法可以考虑这样的转化:添加一个 \(n+1\) 号位并接链成环(?),将原先在链上走转化为在环上走,那么 \(a\) 符合条件当且仅当 \(n+1\) 位置最后没有被占。由于这 \(n+1\) 个点组成一个环,故 \(n+1\) 个点是对称的,它们被占的概率都是相同的,为 \(\dfrac{1}{n+1}\),因此合法的 \(a\) 的个数就是总序列数乘 \(\dfrac{1}{n+1}\),即 \((n+1)^{n-1}\)(注意:这里我们要做一个微调,即将 \(a_i\) 的上界扩大到 \(n+1\),否则就无法保证每个点都是对称的了,这个 \(\dfrac{1}{n+1}\) 也就不成立了,故总序列个数实际上是 \((n+1)^n\),并且如果 \(\exists a_i=n+1\) 那么肯定就不合法了,因此你改就改呗,也不影响我合法的序列 \(a\) 的个数)。

到这里我们只分析完了序列 \(a\) 的性质,即将序列 \(a\) 的贡献全当作 \(1\) 来算后得到的答案,可实际上对于某个 \(a\) 它对答案的贡献并不是 \(1\),而是 \(\sum\limits_{i=1}^{n+1}c_i^k\),其中 \(c_i\) 为 \(i\) 的出现次数。这时候又到了动用咱们聪明才智的时候了。考虑继续分析 \(a\) 的性质,还是从「\(n+1\) 个点组成一个环」这个条件入手,显然我们将每个点都向右平移 \(C\) 格后每个数的出现次数不变,即合法的 \(b\) 的个数 \(cntb(a)\) 不变,但最后留下来的位置也会跟着平移 \(C\) 格。因此考虑对每个合法的序列 \(a\) 做 \(n\) 次映射,即 \(a_i:=(a_i+C-1)\bmod(n+1)+1\),\(C=1,2,3,\cdots,n\)。由于 \(a\) 是合法的序列,故映射后的序列肯定不是合法序列,显然这 \(n+1\) 个序列的 \(cntb\) 都是相同的,又所有合法序列映射后肯定恰好包含全部序列,因此我们可以求出所有序列的答案之和后除以 \(n+1\) 即可算出答案。

接下来考虑怎么计算所有序列的答案之和,显然每个数的贡献都是相同的,计算出一个数的贡献后乘以 \(n+1\) 即为总贡献,又最后要除掉一个 \(n+1\),他俩刚好怼调了。计算一个数的贡献还算好办,枚举出现次数排列组合求一下即可,即

\[\text{ans}=\sum\limits_{i=0}^n\dbinom{n}{i}i^kn^{n-i}
\]

接下来就是愉快地推式子环节了,至此我们进入了本题的第二部分:

\[\begin{aligned}
\text{ans}&=\sum\limits_{i=0}^n\dbinom{n}{i}i^kn^{n-i}
\\&=\sum\limits_{i=0}^n\dbinom{n}{i}n^{n-i}\sum\limits_{j=0}^i\begin{Bmatrix}k\\j\end{Bmatrix}j!\dbinom{i}{j}&(\text{第二类斯特林数的性质})
\\&=\sum\limits_{i=0}^n\sum\limits_{j=0}^i\dbinom{n}{i}\dbinom{i}{j}n^{n-i}\begin{Bmatrix}k\\j\end{Bmatrix}j!
\\&=\sum\limits_{i=0}^n\sum\limits_{j=0}^i\dbinom{n}{j}\dbinom{n-j}{i-j}n^{n-i}\begin{Bmatrix}k\\j\end{Bmatrix}j!&(\text{吸收恒等式})
\\&=\sum\limits_{j=0}^n\dbinom{n}{j}\begin{Bmatrix}k\\j\end{Bmatrix}j!\sum\limits_{i=j}^n\dbinom{n-j}{i-j}n^{n-i}&(\text{交换求和号})
\\&=\sum\limits_{j=0}^n\dbinom{n}{j}\begin{Bmatrix}k\\j\end{Bmatrix}j!\sum\limits_{i=0}^{n-j}\dbinom{n-j}{i}n^{n-i-j}·1^i
\\&=\sum\limits_{j=0}^n\dbinom{n}{j}\begin{Bmatrix}k\\j\end{Bmatrix}j!(n+1)^{n-j}
\end{aligned}
\]

\(\begin{Bmatrix}k\\j\end{Bmatrix}\) 可以通过第二类斯特林数·行求出,于是这道二合一的缝合怪题终于做完了(

  1. const int MAXP=1<<18;
  2. const int MAXN=1e5;
  3. const int pr=3;
  4. const int MOD=998244353;
  5. const int ipr=(MOD+1)/3;
  6. int qpow(int x,int e){
  7. int ret=1;
  8. for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
  9. return ret;
  10. }
  11. int n,k,rev[MAXP+5],fac[MAXN+5],ifac[MAXN+5];
  12. void init_fac(int n){
  13. for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
  14. for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
  15. }
  16. void NTT(vector<int> &a,int len,int type){
  17. int lg=31-__builtin_clz(len);
  18. for(int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<lg-1);
  19. for(int i=0;i<len;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
  20. for(int i=2;i<=len;i<<=1){
  21. int W=qpow((type<0)?ipr:pr,(MOD-1)/i);
  22. for(int j=0;j<len;j+=i){
  23. for(int k=0,w=1;k<(i>>1);k++,w=1ll*w*W%MOD){
  24. int X=a[j+k],Y=1ll*a[(i>>1)+j+k]*w%MOD;
  25. a[j+k]=(X+Y)%MOD;a[(i>>1)+j+k]=(X-Y+MOD)%MOD;
  26. }
  27. }
  28. }
  29. if(type==-1){
  30. int ivn=qpow(len,MOD-2);
  31. for(int i=0;i<len;i++) a[i]=1ll*a[i]*ivn%MOD;
  32. }
  33. }
  34. vector<int> conv(vector<int> a,vector<int> b){
  35. int LEN=1;while(LEN<a.size()+b.size()) LEN<<=1;
  36. a.resize(LEN,0);b.resize(LEN,0);NTT(a,LEN,1);NTT(b,LEN,1);
  37. for(int i=0;i<LEN;i++) a[i]=1ll*a[i]*b[i]%MOD;
  38. NTT(a,LEN,-1);return a;
  39. }
  40. int main(){
  41. scanf("%d%d",&n,&k);init_fac(k);
  42. vector<int> a(k+1),b(k+1);
  43. for(int i=0;i<=k;i++){
  44. a[i]=(i&1)?(MOD-ifac[i]):ifac[i];
  45. b[i]=1ll*qpow(i,k)*ifac[i]%MOD;
  46. } a=conv(a,b);int cur=1,ans=0;
  47. for(int j=1;j<=min(n,k);j++){
  48. cur=1ll*cur*(n-j+1)%MOD*qpow(j,MOD-2)%MOD;
  49. ans=(ans+1ll*a[j]*fac[j]%MOD*cur%MOD*qpow(n+1,n-j))%MOD;
  50. } printf("%d\n",ans);
  51. return 0;
  52. }

Codeforces 1528F - AmShZ Farm(转化+NTT+推式子+第二类斯特林数)的更多相关文章

  1. BZOJ5093 图的价值——推式子+第二类斯特林数

    原题链接 题解 题目等价于求这个式子 \[ans=n2^{\frac{(n-1)(n-2)}{2}}\sum\limits_{i=0}^{n-1}\binom{n-1}{i}i^k\] 有这么一个式子 ...

  2. Codeforces 1097G - Vladislav and a Great Legend(第二类斯特林数+树上背包)

    Codeforces 题目传送门 & 洛谷题目传送门 首先看到这题我的第一反应是:这题跟这题长得好像,不管三七二十一先把 \(k\) 次方展开成斯特林数的形式,\(f(X)^k=\sum\li ...

  3. 【BZOJ 4555】[Tjoi2016&Heoi2016]求和 多项式求逆/NTT+第二类斯特林数

    出处0.0用到第二类斯特林数的性质,做法好像很多,我打的是直接ntt,由第二类斯特林数的容斥公式可以推出,我们可以对于每一个i,来一次ntt求出他与所有j组成的第二类斯特林数的值,这个时候我们是O(n ...

  4. bzoj 4555 [Tjoi2016&Heoi2016]求和——NTT+第二类斯特林数

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4555 第二类斯特林数展开式: \( S(i,j) = \frac{1}{j!} \sum\l ...

  5. bzoj 5093 图的价值 —— 第二类斯特林数+NTT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5093 每个点都是等价的,从点的贡献来看,得到式子: \( ans = n * \sum\li ...

  6. 【BZOJ4555】【TJOI2016】【HEOI2016】求和 (第二类斯特林数+NTT卷积)

    Description 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: $$f(n)=\sum_{i=0}^n\sum_{j=0}^i S(i,j)\tim ...

  7. 【bzoj4555】[Tjoi2016&Heoi2016]求和(NTT+第二类斯特林数)

    传送门 题意: 求 \[ f(n)=\sum_{i=0}^n\sum_{j=0}^i\begin{Bmatrix} i \\ j \end{Bmatrix}2^jj! \] 思路: 直接将第二类斯特林 ...

  8. 【bzoj5093】[Lydsy1711月赛]图的价值(NTT+第二类斯特林数)

    题意: 给定\(n\)个点,一个图的价值定义为所有点的度数的\(k\)次方之和. 现在计算所有\(n\)个点的简单无向图的价值之和. 思路: 将式子列出来: \[ \sum_{i=1}^n\sum_{ ...

  9. BZOJ 4555:[TJOI2016&HEOI2016]求和(第二类斯特林数+NTT)

    题目链接 \(Description\) 求 \[\sum_{i=0}^n\sum_{j=0}^iS(i,j)2^jj!\]对998244353取模后的结果. \(n<=10^5\) \(Sol ...

随机推荐

  1. 【数据结构与算法Python版学习笔记】图——骑士周游问题 深度优先搜索

    骑士周游问题 概念 在一个国际象棋棋盘上, 一个棋子"马"(骑士) , 按照"马走日"的规则, 从一个格子出发, 要走遍所有棋盘格恰好一次.把一个这样的走棋序列 ...

  2. [敏捷软工团队博客]Beta设计和计划

    项目 内容 2020春季计算机学院软件工程(罗杰 任健) 博客园班级博客 作业要求 Beta设计和计划 我们在这个课程的目标是 在团队合作中锻炼自己 这个作业在哪个具体方面帮助我们实现目标 对Beta ...

  3. 聊聊 Kubernetes Pod or Namespace 卡在 Terminating 状态的场景

    这个话题,想必玩过kubernetes的同学当不陌生,我会分Pod和Namespace分别来谈. 开门见山,为什么Pod会卡在Terminationg状态? 一句话,本质是API Server虽然标记 ...

  4. Linux多线程编程实例解析

    Linux系统下的多线程遵循POSIX线程接口,称为 pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a.顺便说一下,Linux ...

  5. 单片机STM32的5个时钟源知识

    众所周知STM32有5个时钟源HSI.HSE.LSI.LSE.PLL,其实他只有四个,因为从上图中可以看到PLL都是由HSI或HSE提供的. 其中,高速时钟(HSE和HSI)提供给芯片主体的主时钟.低 ...

  6. sed 替换命令使用

    输入文件不会被修改,sed 只在模式空间中执行替换命令,然后输出模式空间的内容.文本文件 employee.txt 101,John Doe,CEO 102,Jason Smith,IT Manage ...

  7. 基于 OSPF 路由的邻居邻接关系发现实践

    1.实验目的 理解 OSPF 邻居关系和 OSPF 邻接关系的含义及差别 观察 OSPF 邻居邻接关系的建立过程 观察 OSPF 链路状态数据库的同步过程 2.实验原理 OSPF 网络中,路由器在发送 ...

  8. Linux curl 命令 使用总结

    简介 curl是一种命令行工具,作用是发出网络请求,然后得到和提取数据,显示在"标准输出"(stdout)上面. 它支持多种协议 查看网页源码 直接在curl命令后加上网址,就可以 ...

  9. tabulate

    ValueError: headers for a list of dicts is not a dict or a keyword from: https://bitbucket.org/astan ...

  10. IO流(二)

    一:字符流 字符输入流 写入文件字符流 import java.io.FileWriter; import java.io.IOException; //fileWriter public class ...