题目链接:

https://jzoj.net/senior/#main/show/6080

题目:

题意:

给定$n,m,u,v$

设$t_i=ui+v$

求$\sum_{k_1+k_2+...+k_m=n}t_1^{k_1}t_2^{k_2}...t_m^{k_m}(k_1,k_2,...,k_m∈N)$

算法一:

对于$m=1$的点,显然答案就是$t_1^n$,快速幂计算即可

获得$5$分

算法二:

对于$m=2$的点,$\sum_{k1+k2=n}t_1^{k_1}t_2^{k_2}=\frac{t_1^{n+1}-t_2^{n+1}}{t1-t2}$

结合算法一获得$15$分

算法三:

这显然可以用生成函数,不妨设$f_i(x)=\sum_{k=0}^{n}t_i^kx^k$

把$f_1(x),f_2(x),...,f_m(x)$全部卷起来,第$n$次项的系数就是答案

用$ntt$优化多项式乘法,时间复杂度$O(Tmn logn)$,结合算法一和算法二得分$40$分

代码

  1. #include<algorithm>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<iostream>
  5. #include<cmath>
  6. using namespace std;
  7. typedef long long ll;
  8.  
  9. const int N=4e6+;
  10. const ll mo=;
  11. inline ll read(){
  12. char ch=getchar();ll s=,f=;
  13. while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
  14. while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
  15. return s*f;
  16. }
  17. ll qpow(ll a,ll b)
  18. {
  19. a%=mo;
  20. ll re=;
  21. for (;b;b>>=,a=a*a%mo) if (b&) re=re*a%mo;
  22. return re;
  23. }
  24. ll wn[];
  25. void pre()
  26. {
  27. for (int i=;i<=;i++)
  28. {
  29. ll t=1ll<<i;
  30. wn[i]=qpow(,(mo-)/t);
  31. }
  32. }
  33. int r[N];
  34. void ntt(int limit,ll *a,int type)
  35. {
  36. for (int i=;i<limit;i++) if (i<r[i]) swap(a[i],a[r[i]]);
  37. for (int len=,id=;len<limit;len<<=)
  38. {
  39. ++id;
  40. for (int k=;k<limit;k+=(len<<))
  41. {
  42. ll w=;
  43. for (int l=;l<len;l++,w=w*wn[id]%mo)
  44. {
  45. ll Nx=a[k+l],Ny=w*a[k+len+l]%mo;
  46. a[k+l]=(Nx+Ny)%mo;
  47. a[k+len+l]=((Nx-Ny)%mo+mo)%mo;
  48. }
  49. }
  50. }
  51. if (type==) return;
  52. reverse(a+,a+limit);
  53. ll inv=qpow(limit,mo-);
  54. for (int i=;i<limit;i++) a[i]=a[i]*inv%mo;
  55. }
  56. ll n,m,u,v;
  57. ll f[N],t[N],g[N];
  58. int main()
  59. {
  60. freopen("ioer.in","r",stdin);
  61. freopen("ioer.out","w",stdout);
  62. int T=read();
  63. while (T--)
  64. {
  65. n=read();m=read();u=read();v=read();
  66. if (m==)
  67. {
  68. ll t1=(u+v)%mo;
  69. printf("%lld\n",qpow(t1,n));
  70. continue;
  71. }
  72. if (m==)
  73. {
  74. ll t1=(u+v)%mo,t2=(*u+v)%mo;
  75. ll inv=qpow(((t1-t2)%mo+mo)%mo,mo-);
  76. ll R1=qpow(t1,n+),R2=qpow(t2,n+);
  77. printf("%lld\n",((R1-R2)%mo+mo)%mo*inv%mo);
  78. continue;
  79. }
  80. for (int i=;i<=n;i++) t[i]=(u*i%mo+v)%mo;
  81. for (int i=;i<=n;i++) f[i]=qpow(t[],i);
  82. pre();
  83. int limit=,L=;
  84. while (limit<=((n+)<<)) limit<<=,L++;
  85. for (int i=;i<limit;i++) r[i]=(r[i>>]>>)|((i&)<<(L-));
  86. for (int i=;i<=m;i++)
  87. {
  88. for (int j=;j<=n;j++) g[j]=qpow(t[i],j);
  89. for (int j=n+;j<limit;j++) g[j]=;
  90. ntt(limit,f,);ntt(limit,g,);
  91. for (int j=;j<limit;j++) f[j]=f[j]*g[j]%mo;
  92. ntt(limit,f,-);
  93. for (int j=n+;j<limit;j++) f[j]=;
  94. }
  95. printf("%lld\n",f[n]);
  96. }
  97. return ;
  98. }

算法四:

算法三可以优化

设$f_i(x)=\sum_{k>=0}^{n}t_i^kx^k=\frac{1}{1-t_ik}$

那么求出$\frac{1}{f_1(x)},\frac{1}{f_2(x)},...,\frac{1}{f_m(x)}$的乘积,可以用分治$ntt$在$O(m log^2m)$的时间复杂度内求出

求出后在$\mod x^{n+1}$下多项式求逆,得到的结果的$n$次项系数即为答案

结合算法一,二得分$60$分

算法五:

之前都没有用到$t_i=ui+v$这个条件

不妨构造下面这么一个问题

假设你有一些球,每个球上标有一个不超过$m$的正整数。标有相同数字
的球可能颜色不同,两个球被认为是相同的,当且仅当它们的数字和它们的
颜色都相同。

数字为$i(i<m)$的球各有u中不同的颜色

数字为m的球有u+v中不同颜色

考虑满足一下条件的序列的数量

• 每个元素都是一个球

• 序列长度为 n + m − 1。

• 所有小于 m 的正整数都在序列中某个球上出现过

• 设从左到右第一个数字为 $i(i < m)$ 的球在序列上的位置为 $p_i$(序列上
位置从左到右,从 $1$ 开始编号),对于任意的$ i < j < m$,满足$p_i<p_j$

为了方便描述,设$p_0=0,p_m=n+m$

枚举 $p1, p2, · · · , p_{m−1}$,位置 $pi(1 ≤ i < m)$ 上的球数字只能是 $i$,在$ p_1$
之前的位置数字只能是 $m$,在 $p_2$ 之前的数字只能是 $m $或$ 1$...... 可以得到
满足条件的序列数为

$\sum_{0<p_1<p_2<...<p_m-1<=n+m-1}(u+v)^{p_1-1}u(2u+v)^{p_2-1-p_1}...u(mu+v)^{n+m-1-p_{m-1}}$

设$k_i=p_i-1-p_{i-1}$,上式可以化简为

$u^{m-1}\sum_{k_1+k_2+...+k_m=n} (u+v)^{k_1}(2u+v)^{k_2}...(mu+v)^{k_m}(k1,k2,...,km∈N)$

上式即题目中给出的问题的答案的 $u^{m−1}$ 倍。只要求出满足条件的序列数就能快速得到原问题的答案。对于每个小于 $m$ 的数字,标有这个数字的球颜色种数都是 $u$,所以小于 $m$ 的数字可以看作是等价的。也就是说,设 $a$ 是 $1,...,m−1$ 的任意一个排列,如果把之前所说的这个序列要满足的第四个条件改为:对于任意$i < j < m$,满足$p_{a_i} < p_{a_j}$,满足条件的序列数仍是 $u^{m−1} \sum_{k_1+···+k_m=n}(u +v)^{k_1} (2u + v)^{k_2}...(mu + v)^{k_m}(k_1, · · · , k_m ∈ N)$

因此,只满足前三个条件的序列数,可以看作是 $a$ 取遍所有 $(m − 1)!$ 种排列,满足对于任意 $i < j < m,p_{a_i} < p_{aj}$ 和前三个条件的序列数的和,即:
$(m-1)!u^{m−1} \sum_{k_1+···+k_m=n}(u +v)^{k_1} (2u + v)^{k_2}...(mu + v)^{k_m}(k_1, · · · , k_m ∈ N)$
所以我们只要算出满足前三个条件的序列数,就可以快速求出原问题的答案。

满足前三个条件序列数可以用容斥原理算出,也就是

$\sum_{k=0}^{m-1}\dbinom{m-1}{k}(-1)^k(mu+v-ku)^{n+m-1}$

所以所求问题的答案为

$\frac{\sum_{k=0}^{m-1}\dbinom{m-1}{k}(-1)^k(mu+v-ku)^{n+m-1}}{(m-1)!u^{m-1}}$

预处理阶乘

时间复杂度$O(m+Tm logn)$,可以得到$100$分

思路清新,代码简单

代码

  1. #include<algorithm>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<cmath>
  5. #include<iostream>
  6. using namespace std;
  7. typedef long long ll;
  8.  
  9. const int M=2e5+;
  10. const ll mo=;
  11. ll n,m,u,v;
  12. ll fac[M],finv[M];
  13. inline ll read()
  14. {
  15. char ch=getchar();ll s=,f=;
  16. while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
  17. while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
  18. return s*f;
  19. }
  20. ll qpow(ll a,ll b)
  21. {
  22. a%=mo;
  23. ll re=;
  24. for (;b;b>>=,a=a*a%mo) if (b&) re=re*a%mo;
  25. return re;
  26. }
  27. void pre()
  28. {
  29. fac[]=;
  30. for (int i=;i<M;i++) fac[i]=fac[i-]*i%mo;
  31. finv[M-]=qpow(fac[M-],mo-);
  32. for (int i=M-;i>=;i--) finv[i]=finv[i+]*(i+)%mo;
  33. }
  34. ll C(ll a,ll b)
  35. {
  36. return fac[a]*finv[b]%mo*finv[a-b]%mo;
  37. }
  38. int main()
  39. {
  40. freopen("ioer.in","r",stdin);
  41. freopen("ioer.out","w",stdout);
  42. pre();
  43. int T=read();
  44. while(T--)
  45. {
  46. n=read();m=read();u=read();v=read();
  47. ll ans=;
  48. for (int k=;k<m;k++)
  49. {
  50. if (k&) ans=(ans-C(m-,k)*qpow(m*u+v-k*u,n+m-)%mo+mo)%mo;
  51. else ans=(ans+C(m-,k)*qpow(m*u+v-k*u,n+m-)%mo)%mo;
  52. }
  53. ll o=qpow(u,m-);
  54. ans=ans*finv[m-]%mo*qpow(o,mo-)%mo;
  55. printf("%lld\n",ans);
  56. }
  57. return ;
  58. }

[jzoj 6080] [GDOI2019模拟2019.3.23] IOer 解题报告 (数学构造)的更多相关文章

  1. [jzoj 6101] [GDOI2019模拟2019.4.2] Path 解题报告 (期望)

    题目链接: https://jzoj.net/senior/#main/show/6101 题目: 题解: 设$f_i$表示从节点$i$到节点$n$的期望时间,$f_n=0$ 最优策略就是如果从$i, ...

  2. [jzoj 6093] [GDOI2019模拟2019.3.30] 星辰大海 解题报告 (半平面交)

    题目链接: https://jzoj.net/senior/#contest/show/2686/2 题目: 题解: 说实话这题调试差不多花了我十小时,不过总算借着这道题大概了解了计算几何的基础知识 ...

  3. [jzoj 6092] [GDOI2019模拟2019.3.30] 附耳而至 解题报告 (平面图转对偶图+最小割)

    题目链接: https://jzoj.net/senior/#main/show/6092 题目: 知识点--平面图转对偶图 在求最小割的时候,我们可以把平面图转为对偶图,用最短路来求最小割,这样会比 ...

  4. [jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)

    题目链接: https://jzoj.net/senior/#main/show/6086 题目: 题解: 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘 这样的子树 ...

  5. [jzoj 4528] [GDOI2019模拟2019.3.26] 要换换名字 (最大权闭合子图)

    题目链接: https://jzoj.net/senior/#contest/show/2683/0 题目: 题解: 不妨枚举一个点,让两颗树都以这个点为根,求联通块要么点数为$0$,要么包括根(即联 ...

  6. [jzoj 6087] [GDOI2019模拟2019.3.26] 获取名额 解题报告 (泰勒展开+RMQ+精度)

    题目链接: https://jzoj.net/senior/#main/show/6087 题目: 题解: 只需要统计$\prod_{i=l}^r (1-\frac{a_i}{x})$ =$exp(\ ...

  7. [jzoj 6084] [GDOI2019模拟2019.3.25] 礼物 [luogu 4916] 魔力环 解题报告(莫比乌斯反演+生成函数)

    题目链接: https://jzoj.net/senior/#main/show/6084 https://www.luogu.org/problemnew/show/P4916 题目: 题解: 注: ...

  8. [JZOJ 5893] [NOIP2018模拟10.4] 括号序列 解题报告 (Hash+栈+map)

    题目链接: https://jzoj.net/senior/#main/show/5893 题目: 题解: 考虑暴力怎么做,我们枚举左端点,维护一个栈,依次加入元素,与栈顶元素和栈内第二个元素相同时弹 ...

  9. [JZOJ 5885] [NOIP2018模拟9.27] 物理实验 解题报告 (思维)

    题目链接: https://jzoj.net/senior/#main/show/5885 题目: 题解: 把$a$数组按升序排序 我们可以枚举$x$,发现对于任意$x$,最优情况下$y$一定等于$x ...

随机推荐

  1. week1 notebook1

    初识Python 一.python介绍 - 解释器: cpython(默认使用) ipython(shell) jpython(java) ironpython rubypython - 编码: as ...

  2. Codeforces Round #446

    Greed #include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector&g ...

  3. 完美解决ios10及以上Safari无法禁止缩放的问题

    移动端web缩放有两种: 1.双击缩放: 2.双指手势缩放. 在iOS 10以前,iOS和Android都可以通过一行meta标签来禁止页面缩放 <meta content="widt ...

  4. parseint和isNaN用法

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

  5. XML 之 命名空间详解

    最近学xml 遇到了点小问题qaq 找了n多的博客大佬,反复看了半小时终于明白了,可能我太蠢了... 基础的知识就不赘述,直接放“栗子”,切重点: <?xml version="1.0 ...

  6. 编译OpenCV遇到Qmake问题

    1.Ubuntu安装OpenCv,出现:qmake: could not exec '/usr/lib/x86_64-linux-gnu/qt4/bin/qmake': No such file or ...

  7. Memory management in RxSwift – DisposeBag

    I’ve noticed a lot of beginners in RxSwift ask about DisposeBag. DisposeBag isn’t a standard thing i ...

  8. iOS runLoop 原理多线程 总结 NSTimer优化

    可以理解为字面意思:Run 表示运行,Loop 表示循环.结合在一起就是运行的循环的意思.哈哈,我更愿意翻译为『跑圈』.直观理解就像是不停的跑圈. RunLoop 实际上是一个对象,这个对象在循环中用 ...

  9. /proc/vmstat 详解

    参考 #cat /proc/vmstat nr_free_pages 20223354 nr_alloc_batch 899 nr_inactive_anon 393025 nr_active_ano ...

  10. C++ STL - queue使用详解

    c++队列模板类的定义在<queue>头文件中,queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型. 下面详细介绍 ...