[2018集训队作业][UOJ450] 复读机 [DP+泰勒展开+单位根反演]

时间:2021-01-23 03:10:39

题面

传送门

思路

本文中所有$m$是原题目中的$k$

首先,这个一看就是$d=1,2,3$数据分治

d=1

不说了,很简单,$m^n$

d=2

先上个$dp$试试

设$dp[i][j]$表示前$i$个复读机用掉了$j$个机会,注意这个东西最后求出来的是分配方案,还要乘以一个$n!$

$dp[i][j]=\sum_{k=0}^j [d|k]\binom{n-j+k}{k}dp[i-1][j-k]$

$dp[i][j]=\sum_{k=0}^j [d|k]\frac{(n-j+k)!}{(n-j)!k!}dp[i-1][j-k]$

$(n-j)!dp[i][j]=\sum_{k=0}^j [d|k]\frac{1}{k!}(n-j+k)!dp[i-1][j-k]$

我们令生成函数$A(x)=\sum_{i=0}{\infty}[d|i]\frac{xi}{i!}$,$B_i(x)=\sum{j=0}^{\infty}(n-j)!dp[i][j]$

那么可以发现$B_{i+1}(x)=B_i(x)\ast A(x)$

也就是答案等于$A^m(x)$的第$n$项系数

我们看这个$A(x)$的形式,发现它下面有一堆阶乘,不由得让我们联想到泰勒展开

(我也不知道这个是怎么联想的不过就这样吧我会再写一篇博客解释的23333)

我们发现$ex=\sum_{i=0}{\infty}\frac{xi}{i!}$,同时$e{-x}=\sum_{i=0}^{\infty} (-1)^i \frac{x^i}{i!}$

那么易得$A(x)=\frac{ex+e{-x}}{2}$

所以$Am(x)=(\frac{ex+e{-x}}{2})m=\frac{1}{2m}\sum_{i=0}m \binom{m}{i}e{(2i-m)x}$

然后我们考虑$n$次项系数,发现最外面应该最后乘上去的$n!$和里面的$\frac{1}{n!}$抵消了,上面$e$的幂剩下的系数是$2i-m$

这样我们可以得到答案的表达式$ANS=\sum_{i=0}^m \binom{m}{i} (2i-m)$

d=3

emmm

我们亲爱的$e$好像用不了了

但是我们这个时候有一个神秘的东西:单位根反演!

单位根反演的公式是:$[d|i]=\frac{1}{d}\sum_{j=0}{d-1}\omega_d{ij}$

其中的$\omega_d^j$表示$d$阶单位根的$j$次方

我们代入上面的公式里面得到:

$A(x)=\sum_{i=0}{\infty}\sum_{j=0}{d-1}\frac{1}{d}\omega_d{ij}\frac{xi}{i!}$

$A(x)=\frac{1}{d}\sum_{i=0}{d-1}e{\omega_dix}$

其实可以看到上面的$d=2$就是这个式子的特殊情况

那么$d=3$怎么搞呢?

我们可以发现模数$19491001$是一个3的倍数+1的形式,那么必然存在一个三阶单位负数根根$g$(考虑费马小定理即可)

我们把这个原根求出来,然后两次暴力展开二项式定理,最后可以得到:

$Am(x)=\frac{1}{3m}\sum_{i=0}^m \sum_{j=0}^{m-i} \binom{m}{i}\binom{m-i}{j}e{(i+gj+g2(m-i-j))x}$

然后就$O(m^2\log m)$做完了

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#define MOD 19491001
#define ll long long
using namespace std;
inline ll read(){
ll re=0,flag=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') flag=-1;
ch=getchar();
}
while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
inline void add(ll &a,ll b){
a+=b;
if(a>=MOD) a-=MOD;
}
inline ll qpow(ll a,ll b){
ll re=1;
while(b){
if(b&1) re=re*a%MOD;
a=a*a%MOD;b>>=1;
}
return re;
}
ll n,m,d,f[1000010],finv[1000010],inv[1000010],g=7,inv3,w1,w2;
void init(){
ll i,len=1000000;
f[0]=f[1]=finv[0]=finv[1]=inv[1]=1;
for(i=2;i<=len;i++) f[i]=f[i-1]*i%MOD;
finv[len]=qpow(f[len],MOD-2);
for(i=len;i>2;i--) finv[i-1]=finv[i]*i%MOD;
for(i=2;i<=len;i++) inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
}
inline ll C(ll x,ll y){
return f[x]*finv[y]%MOD*finv[x-y]%MOD;
}
int main(){
n=read();m=read();d=read();
ll i,j;ll ans=0,tmp;init();
inv3=qpow(3,MOD-2);
w1=qpow(g,(MOD-1)/3);
w2=w1*w1%MOD;
if(d==1) cout<<qpow(m,n)<<'\n';
if(d==2){
for(i=0;i<=m;i++){
add(ans,C(m,i)*qpow((2*i-m+MOD)%MOD,n)%MOD);
}
cout<<ans*qpow(qpow(2,m),MOD-2)%MOD<<'\n';
}
if(d==3){
for(i=0;i<=m;i++){
for(j=0;j<=m-i;j++){
tmp=(i+w1*j+w2*(m-i-j))%MOD;
add(ans,C(m,i)*C(m-i,j)%MOD*qpow(tmp,n)%MOD);
}
}
cout<<ans*qpow(qpow(3,m),MOD-2)%MOD<<'\n';
}
}

[2018集训队作业][UOJ450] 复读机 [DP+泰勒展开+单位根反演]的更多相关文章

  1. 处女座与复读机 DP

    题目链接:https://ac.nowcoder.com/acm/contest/327/G 题意:给你两个字符串序列,让你根据第二个序列判断是不是 复读机,复读机会有以下特征 1.       将任 ...

  2. 【做题】UOJ450 - 复读机——单位根反演

    原文链接 https://www.cnblogs.com/cly-none/p/UOJ450.html 题意:请自行阅读. 考虑用生成函数来表示答案.因为秒之间是有序的,所以这应当是个指数生成函数.故 ...

  3. UOJ450 复读机

    题意:n个位置,k种颜色.求有多少种方案使得每种颜色恰出现d的倍数次. 解:d=1就快速幂,n,k很小就DP,记得乘组合数来分配位置. d = 2 / 3的时候,考虑生成函数. f(x) = ∑[d ...

  4. &lbrack;2018集训队作业&rsqb;&lbrack;UOJ424&rsqb; count &lbrack;笛卡尔树&plus;括号序列&plus;折线法&plus;组合数学&rsqb;

    题面 请务必不要吐槽我的标签 传送门 思路 一个很重要的结论:原序列的一组同构的解等价于同一棵拥有$n$个节点的笛卡尔树 注意笛卡尔树的定义:父亲节点是区间最值,并且分割区间为左右部分 所以如果两个序 ...

  5. 【UOJ&num;450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  6. UOJ&num;450&period; 【集训队作业2018】复读机 排列组合 生成函数 单位根反演

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ450.html 题解 首先有一个东西叫做“单位根反演”,它在 FFT 的时候用到过: $$\frac 1 ...

  7. UOJ &num;450&period; 【集训队作业2018】复读机

    前置知识单位根反演自己去浅谈单位根反演看(此外可能需要一定的生成函数的姿势) 首先一看\(d\)这么小,那我们来分类讨论一下吧 当\(d=1\)时,显然答案就是\(k^n\) 当\(d=2\)时,如果 ...

  8. 【UOJ&num;450】&lbrack;集训队作业2018&rsqb; 复读机

    题目链接 题目描述 群里有\(k\)个不同的复读机.为了庆祝平安夜的到来,在接下来的\(n\)秒内,它们每秒钟都会选出一位优秀的复读机进行复读.非常滑稽的是,一个复读机只有总共复读了\(d\)的倍数次 ...

  9. UOJ &num;450「集训队作业2018」复读机

    UOJ #450 题意 有$ k$台复读机,每时每刻有且只有一台复读机进行复读 求$ n$时刻后每台复读机的复读次数都是$ d$的倍数的方案数 $ 1\leq d \leq 3,k \leq 5·10 ...

随机推荐

  1. EF CodeFirst 使用T4模板 生成文件

    小编是个实用主义者,并没有深入的去理解T4的原理.只是根据自己的需求,在博客园里的前辈哪里找的资料,结合自己的理解,在项目中使用了T4模板. 最近的项目用了他,很方便,节省了不少代码量. 想利用T4做 ...

  2. nodejs&colon; C&plus;&plus;扩展

    Nodejs的C++扩展首先保证nodejs和v8都正确安装 下载NodeJS源码,我的放在D盘. NodeJS的C++扩展要用VS2010开发,新建一个空的Win32控制台项目,右键——属性,在常规 ...

  3. SQL中的连接可以分为内连接,外连接,以及交叉连接 。

    SQL中的连接可以分为内连接,外连接,以及交叉连接 . 1. 交叉连接CROSS JOIN 如果不带WHERE条件子句,它将会返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积: 举例, ...

  4. year:2017 month:7 day:17

    2017-07-17 JavaScript 1.javascript 中的运算符 (1)算数运算符:+ ,- ,* ,/ ,% (2)位运算符:& ,| ,~  ,^ ,<< (左 ...

  5. 前端MVC Vue2学习总结(二)——Vue的实例、生命周期与Vue脚手架(vue-cli)

    一.Vue的实例 1.1.创建一个 Vue 的实例 每个 Vue 应用都是通过 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 虽然没有完全遵循 ...

  6. Thread类中的静态方法

    1.currentThread() currentThread()方法返回的是对当前正在执行线程对象的引用. package thread; /** * 线程类的构造方法.静态块是被main线程调用的 ...

  7. 根据地址查询经纬度Js

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>根据地址查询经纬度</ ...

  8. dns相关

    一 用于dns, whois相关的网站 1 http://viewdns.info/iphistory 2 http://bgp.he.net/ 3 https://whois.aliyun.com/ ...

  9. centos6&period;6安装hadoop-2&period;5&period;0(四、hadoop HA安装)

    操作系统:centos6.6 环境:selinux disabled:iptables off:java 1.8.0_131 安装包:hadoop-2.5.0.tar.gz HA模式下的HADOOP完 ...

  10. java json和对象互相装换

    java json和对象互相装换 1.com.alibaba.fastjson.JSON 2.com.fasterxml.jackson.databind.ObjectMapper