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

题面

UOJ

题解

似乎是\(\mbox{Anson}\)爷的题。

\(d=1\)的时候,随便怎么都行,答案就是\(k^n\)。

\(d=2\)的时候,可以做一个\(dp\),设\(f[i][j]\)表示前\(i\)个复读机选了\(j\)个时间的方案数。

然后枚举当前这个复读机复读的次数,得到:

\[f[x][j]=\sum_{i=0}^{j}[2|i]{n-j+i\choose i}f[x-1][j-i]
\]

化简啥的之后得到

\[(n-j)!f[x][j]=\sum_{i=0}^{j}[2|i]\frac{1}{i!}(n-j+i)!f[x-1][j-i]
\]

那么对于\((n-j)!f_j\)构建生成函数,那么等价于每加入一个数就乘上了一个\(A(x)=\sum_{i=0}^{\infty}[2|i]\frac{1}{i!}x^i\)

化简之后就是\(A(x)=\frac{e^x+e^{-x}}{2}\)。

所以最终的答案就是\(A(x)^k[n]\),即\((\frac{e^x+e^{-x}}{2})^k[x^n]\)。

把那个除二搞出来,拿二项式定理算算得到\(\displaystyle \sum_{i=0}^k{k\choose i}e^{(2i-k)x}\) 。

所以\(n\)次项系数就是\((2i-k)^n\)。

最后就是对于\(d=3\)的情况,

推出来的式子就是

\[\sum_{i=0}^k[3|i]\frac{1}{i!}x^i
\]

实际上没必要拿\(dp\)方程来推,可以直接用生成函数考虑。如果确定了每个复读机复读的次数,那么总方案实际上就是\(n!\)除上每个复读机复读次数的阶乘。这个可重排列可以直接推出这个生成函数。

然后发现不会算,前面那个\([3|i]\)不会搞,这样子就可以丢一脸的单位根反演出来:

\[[d|i]=\frac{1}{d}\sum_{j=0}^{d-1}\omega_d^{ij}
\]

然后原式就变成了

\[\frac{1}{d}\sum_{i=0}^k\sum_{j=0}^{d-1}\omega_d^{ij}\frac{1}{i!}x^i
\]

也就是

\[\frac{1}{d}\sum_{j=0}^{d-1}e^{\omega_d^{j}x}
\]

要求的是这个东西的\(k\)次方,也就是

\[\frac{1}{d^k}(\sum_{i=0}^{d-1}e^{\omega_d^{j}x})^k
\]

而\(d=3\)的时候\(k\)很小,直接\(O(k^2)\)暴力二项式定理给他展开就好了。

至于单位根怎么求?

求出模数\(p\)的原根\(g\),我们知道\(g^{p-1}\equiv 1(mod\ p)\),而\(\omega_d^d\equiv 1(mod\ p)\)。所以有\(\omega_d=g^{\frac{p-1}{d}}\)。

那么算出来之后就可以\(O(k^2\log n)\)计算答案了。

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. #define MOD 19491001
  5. #define MAX 500500
  6. int fpow(int a,int b)
  7. {
  8. int s=1;
  9. while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
  10. return s;
  11. }
  12. int n,k,d,ans;
  13. int jc[MAX],jv[MAX],inv[MAX];
  14. int C(int n,int m){if(n<m||n<0)return 0;return 1ll*jc[n]*jv[m]%MOD*jv[n-m]%MOD;}
  15. int main()
  16. {
  17. scanf("%d%d%d",&n,&k,&d);
  18. if(d==1){printf("%d\n",fpow(k,n));return 0;}
  19. jc[0]=jv[0]=inv[0]=inv[1]=1;
  20. for(int i=2;i<=k;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
  21. for(int i=1;i<=k;++i)jc[i]=1ll*jc[i-1]*i%MOD;
  22. for(int i=1;i<=k;++i)jv[i]=1ll*jv[i-1]*inv[i]%MOD;
  23. if(d==2)
  24. {
  25. for(int i=0;i<=k;++i)ans=(ans+1ll*C(k,i)*fpow((i+i-k+MOD)%MOD,n))%MOD;
  26. ans=1ll*ans*fpow(fpow(2,k),MOD-2)%MOD;
  27. printf("%d\n",ans);
  28. }
  29. else
  30. {
  31. int w1=fpow(7,(MOD-1)/3),w2=1ll*w1*w1%MOD;
  32. for(int i=0;i<=k;++i)
  33. for(int j=0;i+j<=k;++j)
  34. {
  35. int p=(1ll*(k-j-i)+1ll*w1*i+1ll*w2*j)%MOD;
  36. ans=(ans+1ll*C(k,i)*C(k-i,j)%MOD*fpow(p,n))%MOD;
  37. }
  38. ans=1ll*ans*fpow(fpow(d,k),MOD-2)%MOD;
  39. printf("%d\n",ans);
  40. }
  41. return 0;
  42. }

【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)的更多相关文章

  1. uoj #450[集训队作业2018]复读机

    传送门 \(d=1\),那么任何时刻都可以\(k\)个复读机的一种,答案为\(k^n\) \(d>1\),可以枚举某个复读机的复读次数(必须是\(d\)的倍数),然后第\(i\)个复读时间为\( ...

  2. 【UOJ#450】[集训队作业2018] 复读机

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

  3. uoj#450. 【集训队作业2018】复读机(单位根反演)

    题面 传送门 题解 我的生成函数和单位根反演的芝士都一塌糊涂啊-- \(d=1\),答案就是\(k^n\)(因为这里\(k\)个复读机互不相同,就是说有标号) \(d=2\),我们考虑复读机的生成函数 ...

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

    题面 传送门 思路 本文中所有$m$是原题目中的$k$ 首先,这个一看就是$d=1,2,3$数据分治 d=1 不说了,很简单,$m^n$ d=2 先上个$dp$试试 设$dp[i][j]$表示前$i$ ...

  5. UOJ 422 [集训队作业2018] 小Z的礼物 min-max容斥 期望 轮廓线dp

    LINK:小Z的礼物 太精髓了 我重学了一遍min-max容斥 重写了一遍按位或才写这道题的. 还是期望多少时间可以全部集齐. 相当于求出 \(E(max(S))\)表示最后一个出现的期望时间. 根据 ...

  6. uoj450 【集训队作业2018】复读机(生成函数,单位根反演)

    uoj450 [集训队作业2018]复读机(生成函数,单位根反演) uoj 题解时间 首先直接搞出单个复读机的生成函数 $ \sum\limits_{ i = 0 }^{ k } [ d | i ] ...

  7. UOJ #449. 【集训队作业2018】喂鸽子

    UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...

  8. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

  9. UOJ#418. 【集训队作业2018】三角形

    #418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...

随机推荐

  1. Navicat还原出现Finished - Stopped before completion的问题

    查看数据库中最大的单个文件容量 SHOW VARIABLES LIKE '%max_allowed_packet%';   设置最大单个文件容量为10M,单次有效(新建查询---运行) SET GLO ...

  2. 【问题解决方案】Dev C++ 无法调试的问题与解决

    听翁恺老师课的时候用到一个叫DevC++的编辑器. 学到调试部分的时候,老师的没问题我的报错.我?? 试一试网上查到的方法: 工具 --> 编译选项 --> 代码生成/优化 --> ...

  3. python自动化常见问题汇总

           1.如何提高selenium脚本的执行速度? Selenium脚本的执行速度受多方面因素的影响,如网速,操作步骤的繁琐程度,页面加载的速度,以及我们在脚本中设置的等待时间,运行脚本的线程 ...

  4. Python3练习题 011:成绩打分

    # print('-----判断输入值和60大小判断')# b=int(input('input num'))# if b >60:# print('良')# elif b==60:# prin ...

  5. [转帖]PAT 计算机程序设计能力考试

    PAT 计算机程序设计能力考试 https://blog.csdn.net/bat67/article/details/52134211 [官方简介] 计算机程序设计能力考试(Programming ...

  6. transform: translate(-50%, -50%) 实现块元素百分比下居中

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  7. VUE项目问题之:去掉url中的#/

    一.问题 使用VUE路由,项目的url总是带有锚点,如下: http://localhost:8082/#/ 二.解决 修改路由文件中 index.js 文件,即 src --> router ...

  8. MySQL索引管理及执行计划

    一.索引介绍 二.explain详解 三.建立索引的原则(规范)

  9. Ubuntu中MySql的启动与关闭

    安装mysql sudo apt-get install mysql-server sudo apt install mysql-client sudo apt install libmysqlcli ...

  10. PDO连接mysql数据库加载慢

    今天在使用PDO连接mysql操作数据库的时候,发现速度特别慢,都1~2s的时间,不知道怎么回事,后来一步一步排除到new PDO 导致过慢的原因, 这个尴尬了...,调试了半天都没想到问下度娘,才知 ...