[2018集训队作业][UOJ450] 复读机 [DP+泰勒展开+单位根反演]
题面
思路
本文中所有$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+泰勒展开+单位根反演]的更多相关文章
- uoj450 【集训队作业2018】复读机(生成函数,单位根反演)
uoj450 [集训队作业2018]复读机(生成函数,单位根反演) uoj 题解时间 首先直接搞出单个复读机的生成函数 $ \sum\limits_{ i = 0 }^{ k } [ d | i ] ...
- 处女座与复读机 DP
题目链接:https://ac.nowcoder.com/acm/contest/327/G 题意:给你两个字符串序列,让你根据第二个序列判断是不是 复读机,复读机会有以下特征 1. 将任 ...
- 【做题】UOJ450 - 复读机——单位根反演
原文链接 https://www.cnblogs.com/cly-none/p/UOJ450.html 题意:请自行阅读. 考虑用生成函数来表示答案.因为秒之间是有序的,所以这应当是个指数生成函数.故 ...
- UOJ450 复读机
题意:n个位置,k种颜色.求有多少种方案使得每种颜色恰出现d的倍数次. 解:d=1就快速幂,n,k很小就DP,记得乘组合数来分配位置. d = 2 / 3的时候,考虑生成函数. f(x) = ∑[d ...
- [2018集训队作业][UOJ424] count [笛卡尔树+括号序列+折线法+组合数学]
题面 请务必不要吐槽我的标签 传送门 思路 一个很重要的结论:原序列的一组同构的解等价于同一棵拥有$n$个节点的笛卡尔树 注意笛卡尔树的定义:父亲节点是区间最值,并且分割区间为左右部分 所以如果两个序 ...
- 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)
[UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...
- UOJ#450. 【集训队作业2018】复读机 排列组合 生成函数 单位根反演
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ450.html 题解 首先有一个东西叫做“单位根反演”,它在 FFT 的时候用到过: $$\frac 1 ...
- UOJ #450. 【集训队作业2018】复读机
前置知识单位根反演自己去浅谈单位根反演看(此外可能需要一定的生成函数的姿势) 首先一看\(d\)这么小,那我们来分类讨论一下吧 当\(d=1\)时,显然答案就是\(k^n\) 当\(d=2\)时,如果 ...
- 【UOJ#450】[集训队作业2018] 复读机
题目链接 题目描述 群里有\(k\)个不同的复读机.为了庆祝平安夜的到来,在接下来的\(n\)秒内,它们每秒钟都会选出一位优秀的复读机进行复读.非常滑稽的是,一个复读机只有总共复读了\(d\)的倍数次 ...
随机推荐
- c的多态
使用函数数组,实现多态 参考my_strtoll10
- uvaoj 10474 - Where is the Marble?(sort+lower_bound)
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- Django - day00 第一个页面
Django - day00 0.写在最前面 第一次接触Django,是在大三的做数据库课程设计的时候,当时好像还是1.8的版本,现转眼就到了2.0的版本. 当时由于没太多的课,仅花了不到一周的时间就 ...
- 了解Python控制流语句——if语句
控制流 截止到现在,在我们所看过的程序中,总是有一系列语句从上到下精确排列,并交由 Python 忠实地执行.如果你想改变这一工作流程,应该怎么做?就像这样的情况:你需要程序作出一些决定,并依据不同的 ...
- informix如何查询第一条记录
1.select first 1 * from shop; 正序查询第一条数据 2.select first 1 * from shop order by create_time desc; 按创建时 ...
- lintcode514 栅栏染色
栅栏染色 我们有一个栅栏,它有n个柱子,现在要给柱子染色,有k种颜色可以染.必须保证不存在超过2个相邻的柱子颜色相同,求有多少种染色方案. 注意事项 n和k都是非负整数 您在真实的面试中是否遇到过这个 ...
- 关于java中的“error: bad operand types for binary operator ”
今天做这个题目的时候(142. O(1) Check Power of 2),遇到一个错误“ bad operand types for binary operator '&' ”. 先贴一下 ...
- Linux系统负载查询
查询Linux系统负载情况,一般需要了解三个方面的信息: 1.Linux系统配置.如Linux版本号.CPU.内存.网络.磁盘等: 2.收集系统负载信息的手段.常用的工具包有sysstat和procp ...
- 剑指offer-字符串的排列26
题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述: 输 ...
- .net转PHP从零开始-环境的搭建
PHP初级开发环境安装很简单,只需要使用一键安装的phpstudy 下载地址:http://www.phpstudy.net/ 安装后可以看到 这样的界面,设置好相关的配置,然后,选择查看phpinf ...