「LOJ 556 Antileaf's Round」咱们去烧菜吧

最近在看 jcvb 的生成函数课件,顺便切一切上面讲到的内容的板子题,这个题和课件上举例的背包计数基本一样。

解题思路

首先列出答案的生成函数:

\[\prod_{1\leq k \leq m}\left(\sum_{0\leq i\leq b_k} x^{ia_k}\right) \\
=\prod_{1\leq k\leq m}\left(\dfrac{1-x^{a_k{(b_k+1)}}}{1-x^{a_k}}\right) \\
=\exp\left(\sum_{1\leq k\leq m}\ln(1-x^{a_k(b_k+1)})-\ln(1-x^{a_k})\right) \\
=\exp\left(\sum_{1\leq k\leq m}\sum_{j\geq1}\dfrac{x^{a_kj}-x^{a_k(b_k+1)j}}{j}\right) \\
\]

\[c_k =\sum_{1\leq i\leq m} [a_i=k]
\\d_k=\sum_{1\leq i\leq m}[a_i(b_i+1)=k] \\
A(x)=\sum_{k}(c_k-d_k)x^k
\]

上面式子等价于

\[=\exp\left(\sum_{j\geq1}\dfrac{1}{j}\sum_{k}(c_k-d_k)x^{jk}\right) \\
=\exp\left(\sum_{j\geq1}\dfrac{1}{j}A(x^j)\right)
\]

因为过程始终在模 \(x^{n+1}\) 次下进行,所以 \(A(x^j)\) 有用的项只有 \(\lfloor\dfrac{n}{j}\rfloor\) 个,可以 \(\mathcal O(n\log n)\) 预处理出

\[\sum_{j\geq1}\dfrac{1}{j}A(x^j)
\]

然后跑一遍多项式 \(\exp\) 就好了,复杂度还是 \(\mathcal O(n\log n)\) 。

这个题数据有问题,当 \(a_i = 0\) 的时候,第一步不能等比数列求和,然而通过此题需要无视 \(a_i = 0\) 的物品,甚至还有 \(a_i=0,b_i=0\) 的情况,所以下面贴一个AC代码,但是实际山来说不是正确的

code

  1. /*program by mangoyang*/
  2. #include<bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int N = (1 << 22) + 5, P = 998244353, G = 3;
  16. namespace poly{
  17. int rev[N], W[N], invW[N], len, lg;
  18. inline int Pow(int a, int b){
  19. int ans = 1;
  20. for(; b; b >>= 1, a = 1ll * a * a % P)
  21. if(b & 1) ans = 1ll * ans * a % P;
  22. return ans;
  23. }
  24. inline void init(){
  25. for(int k = 2; k < N; k <<= 1)
  26. W[k] = Pow(G, (P - 1) / k), invW[k] = Pow(W[k], P - 2);
  27. }
  28. inline void timesinit(int lenth){
  29. for(len = 1, lg = 0; len <= lenth; len <<= 1, lg++);
  30. for(int i = 0; i < len; i++)
  31. rev[i] = (rev[i>>1] >> 1) | ((i & 1) << (lg - 1));
  32. }
  33. inline void DFT(int *a, int sgn){
  34. for(int i = 0; i < len; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
  35. for(int k = 2; k <= len; k <<= 1){
  36. int w = ~sgn ? W[k] : invW[k];
  37. for(int i = 0; i < len; i += k){
  38. int now = 1;
  39. for(int j = i; j < i + (k >> 1); j++){
  40. int x = a[j], y = 1ll * a[j+(k>>1)] * now % P;
  41. a[j] = (x + y) % P, a[j+(k>>1)] = (x - y + P) % P;
  42. now = 1ll * now * w % P;
  43. }
  44. }
  45. }
  46. if(sgn == -1){
  47. int Inv = Pow(len, P - 2);
  48. for(int i = 0; i < len; i++) a[i] = 1ll * a[i] * Inv % P;
  49. }
  50. }
  51. inline void getinv(int *a, int *b, int n){
  52. static int tmp[N];
  53. if(n == 1) return (void) (b[0] = Pow(a[0], P - 2));
  54. getinv(a, b, (n + 1) / 2);
  55. timesinit(n * 2 - 1);
  56. for(int i = 0; i < len; i++) tmp[i] = i < n ? a[i] : 0;
  57. DFT(tmp, 1), DFT(b, 1);
  58. for(int i = 0; i < len; i++)
  59. b[i] = 1ll * (2 - 1ll * tmp[i] * b[i] % P + P) % P * b[i] % P;
  60. DFT(b, -1);
  61. for(int i = n; i < len; i++) b[i] = 0;
  62. for(int i = 0; i < len; i++) tmp[i] = 0;
  63. }
  64. inline void getsqrt(int *a, int *b, int n){
  65. static int tmp1[N], tmp2[N];
  66. if(n == 1) return (void) (b[0] = 1);
  67. getsqrt(a, b, (n + 1) / 2);
  68. for(int i = 0; i < n; i++) tmp1[i] = a[i];
  69. getinv(b, tmp2, n), timesinit(n * 2 - 1);
  70. DFT(tmp1, 1), DFT(tmp2, 1);
  71. for(int i = 0; i < len; i++) tmp1[i] = 1ll * tmp1[i] * tmp2[i] % P;
  72. DFT(tmp1, -1);
  73. for(int i = 0; i < len; i++)
  74. b[i] = 1ll * (b[i] + tmp1[i]) % P * Pow(2, P - 2) % P;
  75. for(int i = n; i < len; i++) b[i] = 0;
  76. for(int i = 0; i < len; i++) tmp1[i] = tmp2[i] = 0;
  77. }
  78. inline void getln(int *a, int *b, int n){
  79. static int tmp[N];
  80. getinv(a, b, n), timesinit(n * 2 - 1);
  81. for(int i = 1; i < n; i++) tmp[i-1] = 1ll * a[i] * i % P;
  82. DFT(tmp, 1), DFT(b, 1);
  83. for(int i = 0; i < len; i++) b[i] = 1ll * tmp[i] * b[i] % P;
  84. DFT(b, -1);
  85. for(int i = len - 1; i; i--) b[i] = 1ll * b[i-1] * Pow(i, P - 2) % P;
  86. b[0] = 0;
  87. for(int i = n; i < len; i++) b[i] = 0;
  88. for(int i = 0; i < len; i++) tmp[i] = 0;
  89. }
  90. inline void getexp(int *a, int *b, int n){
  91. static int tmp[N];
  92. if(n == 1) return (void) (b[0] = 1);
  93. getexp(a, b, (n + 1) / 2);
  94. getln(b, tmp, n), timesinit(n * 2 - 1);
  95. for(int i = 0; i < n; i++) tmp[i] = (!i - tmp[i] + a[i] + P) % P;
  96. DFT(tmp, 1), DFT(b, 1);
  97. for(int i = 0; i < len; i++) b[i] = 1ll * b[i] * tmp[i] % P;
  98. DFT(b, -1);
  99. for(int i = n; i < len; i++) b[i] = 0;
  100. for(int i = 0; i < len; i++) tmp[i] = 0;
  101. }
  102. inline void power(int *a, int *b, int n, int m, ll k){
  103. static int tmp[N];
  104. for(int i = 0; i < m; i++) b[i] = 0;
  105. int fir = -1;
  106. for(int i = 0; i < n; i++) if(a[i]){ fir = i; break; }
  107. if(fir && k >= m) return;
  108. if(fir == -1 || 1ll * fir * k >= m) return;
  109. for(int i = fir; i < n; i++) b[i-fir] = a[i];
  110. for(int i = 0; i < n - fir; i++)
  111. b[i] = 1ll * b[i] * Pow(a[fir], P - 2) % P;
  112. getln(b, tmp, m);
  113. for(int i = 0; i < m; i++)
  114. b[i] = 1ll * tmp[i] * (k % P) % P, tmp[i] = 0;
  115. getexp(b, tmp, m);
  116. for(int i = m; i >= fir * k; i--)
  117. b[i] = 1ll * tmp[i-fir*k] * Pow(a[fir], k % (P - 1)) % P;
  118. for(int i = 0; i < fir * k; i++) b[i] = 0;
  119. for(int i = 0; i < m; i++) tmp[i] = 0;
  120. }
  121. }
  122. using poly::Pow;
  123. using poly::DFT;
  124. using poly::timesinit;
  125. int a[N], b[N], A[N], f[N], g[N], n, m;
  126. int main(){
  127. poly::init(), read(n), read(m);
  128. for(int i = 1; i <= m; i++){
  129. read(a[i]), read(b[i]);
  130. if(!b[i]) b[i] = n / a[i];
  131. if(a[i] <= n) A[a[i]]++;
  132. if(1ll * a[i] * (b[i] + 1) <= n) A[a[i]*(b[i]+1)]--;
  133. }
  134. for(int i = 0; i <= n; i++) (A[i] += P) %= P;
  135. for(int j = 1; j <= n; j++){
  136. int Inv = Pow(j, P - 2);
  137. for(int i = 1; i <= n / j; i++)
  138. (f[i*j] += 1ll * A[i] * Inv % P) %= P;
  139. }
  140. poly::getexp(f, g, n + 1);
  141. for(int i = 1; i <= n; i++) printf("%d\n", g[i]);
  142. return 0;
  143. }

「LOJ 556 Antileaf's Round」咱们去烧菜吧的更多相关文章

  1. LOJ #556. 「Antileaf's Round」咱们去烧菜吧

    好久没更博了 咕咕咕 现在多项式板子的常数巨大...周末好好卡波常吧.... LOJ #556 题意 给定$ m$种物品的出现次数$ B_i$以及大小$ A_i$ 求装满大小为$[1..n]$的背包的 ...

  2. 【刷题】LOJ 556 「Antileaf's Round」咱们去烧菜吧

    题目描述 你有 \(m\) 种物品,第 \(i\) 种物品的大小为 \(a_i\) ​,数量为 \(b_i\)​( \(b_i=0\) 表示有无限个). 你还有 \(n\) 个背包,体积分别为 \(1 ...

  3. LOJ#557. 「Antileaf's Round」你这衣服租来的吗(FHQ Treap+珂朵莉树)

    题面 传送门 题解 好吧我是不太会复杂度分析-- 我们对于每种颜色用一个数据结构维护(比方说线段树或者平衡树,代码里写的平衡树),那么区间询问很容易就可以解决了 所以现在的问题是区间修改,如果区间颜色 ...

  4. loj558 「Antileaf's Round」我们的CPU遭到攻击

    考完了可以发题解了. 做法是link-cut tree维护子树信息,并不需要维护黑树白树那些的. 下面是一条重链: 如果4是根的话,那么在splay上是这样的: 在splay中,子树的信息都已经计算完 ...

  5. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  6. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

  7. [LOJ 6029]「雅礼集训 2017 Day1」市场

    [LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...

  8. 「LOJ#10051」「一本通 2.3 例 3」Nikitosh 和异或(Trie

    题目描述 原题来自:CODECHEF September Challenge 2015 REBXOR 1​​≤r​1​​<l​2​​≤r​2​​≤N,x⨁yx\bigoplus yx⨁y 表示 ...

  9. LOJ#10117. 「一本通 4.1 练习 2」简单题

    LOJ#10117. 「一本通 4.1 练习 2」简单题 题目描述 题目来源:$CQOI 2006$ 有一个$n$个元素的数组,每个元素初始均为$0$.有$m$条指令,要么让其中一段连续序列数字反转— ...

随机推荐

  1. Tomcat权威指南-读书摘要系列10

    Tomcat集群 一些集群技术 DNS请求分配 TCP网络地址转换请求分配 Mod_proxy_balance负载均衡与故障复原 JDBC请求分布与故障复原

  2. 2018年9月28日CCPC秦皇岛站参赛总结

    day1: 被中间结果超出int范围给叉了,立刻意识到了自己的弱小以及校赛出题的时候是怎么叉别人的 day2: 签到签了40分钟,谨慎一些还是很好的,机子重启耽误了一些时间 一道暴力+LCS的简单题被 ...

  3. 为ASP.NET控件加入快捷菜单

    ContextMenu Control 快捷菜单控件概述: MSDN Liabrary 中包含了几个DHTML快捷菜单的示例.分别提供了对这一功能的不能实现方法.一个快捷菜单就是在页面中任何位置的一组 ...

  4. Android手机间无线互传功能探索及实现

    年前研究了一下Android如何实现无线互传的功能,写了个小demo,最近无事,遂整理一下,与各位共享.前期调研发现,Android想要实现无线互传有以下几种技术:1,Bluetooth通行已久,简单 ...

  5. Integer中1000==1000为false而100==100为true

    查看Integer.java类,会发现有一个内部私有类,IntegerCache.java,它缓存了从-128到127之间的所有的整数对象.如果在这个区间内,他就会把变量当做一个变量,放到内存中:但如 ...

  6. git与代码托管工具

    1.git初识 git是一个版本管理工具,用来管理项目的不同的版本,记录下不同的提交记录,git还可以构建不同的分支,用来给不同的人来推送使用. 推荐的git教程:https://www.cnblog ...

  7. 3.微信公众号开发:配置与微信公众平台服务器交互的URL接口地址

    微信开发基本原理: 1.首先有3个对象 分别是微信用户端 微信公众平台服务器 开发者服务器(也就是放自己代码的服务器) 三者间互相交互 2.微信公众平台服务器 充当中间者角色 (以被动回复消息为例) ...

  8. vim助手

    移动光标 hjkl 2w 向前移动两个单词 3e 向前移动到第 3 个单词的末尾 0 移动到行首 $ 当前行的末尾 gg 文件第一行 G 文件最后一行 行号+G 指定行 <ctrl>+o ...

  9. 001_关于选中的磁盘具有MBR分区表。在 EFI 系统上,Windows 只能安装到 GPT 磁盘。问题解决

    问题: 今天我的diy电脑重装系统时,遇到了一个棘手的问题.在选择安装分区的时候,提示有这样的错误. Windows 无法安装到这个磁盘.选中的磁盘具有MBR分区表.在 EFI 系统上,Windows ...

  10. java 遍历指定目录下的文件夹并查找包含指定关键字的文件

    输入指定关键字,在制定目录中查找包含关键字的文件,返回包含指定关键字的文件路径. package net.xsoftlab.baike; import java.io.File; import jav ...