「LOJ 556 Antileaf's Round」咱们去烧菜吧
「LOJ 556 Antileaf's Round」咱们去烧菜吧
最近在看 jcvb 的生成函数课件,顺便切一切上面讲到的内容的板子题,这个题和课件上举例的背包计数基本一样。
解题思路
首先列出答案的生成函数:
=\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) \\
\]
令
\\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}A(x^j)\right)
\]
因为过程始终在模 \(x^{n+1}\) 次下进行,所以 \(A(x^j)\) 有用的项只有 \(\lfloor\dfrac{n}{j}\rfloor\) 个,可以 \(\mathcal O(n\log n)\) 预处理出
\]
然后跑一遍多项式 \(\exp\) 就好了,复杂度还是 \(\mathcal O(n\log n)\) 。
这个题数据有问题,当 \(a_i = 0\) 的时候,第一步不能等比数列求和,然而通过此题需要无视 \(a_i = 0\) 的物品,甚至还有 \(a_i=0,b_i=0\) 的情况,所以下面贴一个AC代码,但是实际山来说不是正确的
code
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = (1 << 22) + 5, P = 998244353, G = 3;
namespace poly{
int rev[N], W[N], invW[N], len, lg;
inline int Pow(int a, int b){
int ans = 1;
for(; b; b >>= 1, a = 1ll * a * a % P)
if(b & 1) ans = 1ll * ans * a % P;
return ans;
}
inline void init(){
for(int k = 2; k < N; k <<= 1)
W[k] = Pow(G, (P - 1) / k), invW[k] = Pow(W[k], P - 2);
}
inline void timesinit(int lenth){
for(len = 1, lg = 0; len <= lenth; len <<= 1, lg++);
for(int i = 0; i < len; i++)
rev[i] = (rev[i>>1] >> 1) | ((i & 1) << (lg - 1));
}
inline void DFT(int *a, int sgn){
for(int i = 0; i < len; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
for(int k = 2; k <= len; k <<= 1){
int w = ~sgn ? W[k] : invW[k];
for(int i = 0; i < len; i += k){
int now = 1;
for(int j = i; j < i + (k >> 1); j++){
int x = a[j], y = 1ll * a[j+(k>>1)] * now % P;
a[j] = (x + y) % P, a[j+(k>>1)] = (x - y + P) % P;
now = 1ll * now * w % P;
}
}
}
if(sgn == -1){
int Inv = Pow(len, P - 2);
for(int i = 0; i < len; i++) a[i] = 1ll * a[i] * Inv % P;
}
}
inline void getinv(int *a, int *b, int n){
static int tmp[N];
if(n == 1) return (void) (b[0] = Pow(a[0], P - 2));
getinv(a, b, (n + 1) / 2);
timesinit(n * 2 - 1);
for(int i = 0; i < len; i++) tmp[i] = i < n ? a[i] : 0;
DFT(tmp, 1), DFT(b, 1);
for(int i = 0; i < len; i++)
b[i] = 1ll * (2 - 1ll * tmp[i] * b[i] % P + P) % P * b[i] % P;
DFT(b, -1);
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp[i] = 0;
}
inline void getsqrt(int *a, int *b, int n){
static int tmp1[N], tmp2[N];
if(n == 1) return (void) (b[0] = 1);
getsqrt(a, b, (n + 1) / 2);
for(int i = 0; i < n; i++) tmp1[i] = a[i];
getinv(b, tmp2, n), timesinit(n * 2 - 1);
DFT(tmp1, 1), DFT(tmp2, 1);
for(int i = 0; i < len; i++) tmp1[i] = 1ll * tmp1[i] * tmp2[i] % P;
DFT(tmp1, -1);
for(int i = 0; i < len; i++)
b[i] = 1ll * (b[i] + tmp1[i]) % P * Pow(2, P - 2) % P;
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp1[i] = tmp2[i] = 0;
}
inline void getln(int *a, int *b, int n){
static int tmp[N];
getinv(a, b, n), timesinit(n * 2 - 1);
for(int i = 1; i < n; i++) tmp[i-1] = 1ll * a[i] * i % P;
DFT(tmp, 1), DFT(b, 1);
for(int i = 0; i < len; i++) b[i] = 1ll * tmp[i] * b[i] % P;
DFT(b, -1);
for(int i = len - 1; i; i--) b[i] = 1ll * b[i-1] * Pow(i, P - 2) % P;
b[0] = 0;
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp[i] = 0;
}
inline void getexp(int *a, int *b, int n){
static int tmp[N];
if(n == 1) return (void) (b[0] = 1);
getexp(a, b, (n + 1) / 2);
getln(b, tmp, n), timesinit(n * 2 - 1);
for(int i = 0; i < n; i++) tmp[i] = (!i - tmp[i] + a[i] + P) % P;
DFT(tmp, 1), DFT(b, 1);
for(int i = 0; i < len; i++) b[i] = 1ll * b[i] * tmp[i] % P;
DFT(b, -1);
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp[i] = 0;
}
inline void power(int *a, int *b, int n, int m, ll k){
static int tmp[N];
for(int i = 0; i < m; i++) b[i] = 0;
int fir = -1;
for(int i = 0; i < n; i++) if(a[i]){ fir = i; break; }
if(fir && k >= m) return;
if(fir == -1 || 1ll * fir * k >= m) return;
for(int i = fir; i < n; i++) b[i-fir] = a[i];
for(int i = 0; i < n - fir; i++)
b[i] = 1ll * b[i] * Pow(a[fir], P - 2) % P;
getln(b, tmp, m);
for(int i = 0; i < m; i++)
b[i] = 1ll * tmp[i] * (k % P) % P, tmp[i] = 0;
getexp(b, tmp, m);
for(int i = m; i >= fir * k; i--)
b[i] = 1ll * tmp[i-fir*k] * Pow(a[fir], k % (P - 1)) % P;
for(int i = 0; i < fir * k; i++) b[i] = 0;
for(int i = 0; i < m; i++) tmp[i] = 0;
}
}
using poly::Pow;
using poly::DFT;
using poly::timesinit;
int a[N], b[N], A[N], f[N], g[N], n, m;
int main(){
poly::init(), read(n), read(m);
for(int i = 1; i <= m; i++){
read(a[i]), read(b[i]);
if(!b[i]) b[i] = n / a[i];
if(a[i] <= n) A[a[i]]++;
if(1ll * a[i] * (b[i] + 1) <= n) A[a[i]*(b[i]+1)]--;
}
for(int i = 0; i <= n; i++) (A[i] += P) %= P;
for(int j = 1; j <= n; j++){
int Inv = Pow(j, P - 2);
for(int i = 1; i <= n / j; i++)
(f[i*j] += 1ll * A[i] * Inv % P) %= P;
}
poly::getexp(f, g, n + 1);
for(int i = 1; i <= n; i++) printf("%d\n", g[i]);
return 0;
}
「LOJ 556 Antileaf's Round」咱们去烧菜吧的更多相关文章
- LOJ #556. 「Antileaf's Round」咱们去烧菜吧
好久没更博了 咕咕咕 现在多项式板子的常数巨大...周末好好卡波常吧.... LOJ #556 题意 给定$ m$种物品的出现次数$ B_i$以及大小$ A_i$ 求装满大小为$[1..n]$的背包的 ...
- 【刷题】LOJ 556 「Antileaf's Round」咱们去烧菜吧
题目描述 你有 \(m\) 种物品,第 \(i\) 种物品的大小为 \(a_i\) ,数量为 \(b_i\)( \(b_i=0\) 表示有无限个). 你还有 \(n\) 个背包,体积分别为 \(1 ...
- LOJ#557. 「Antileaf's Round」你这衣服租来的吗(FHQ Treap+珂朵莉树)
题面 传送门 题解 好吧我是不太会复杂度分析-- 我们对于每种颜色用一个数据结构维护(比方说线段树或者平衡树,代码里写的平衡树),那么区间询问很容易就可以解决了 所以现在的问题是区间修改,如果区间颜色 ...
- loj558 「Antileaf's Round」我们的CPU遭到攻击
考完了可以发题解了. 做法是link-cut tree维护子树信息,并不需要维护黑树白树那些的. 下面是一条重链: 如果4是根的话,那么在splay上是这样的: 在splay中,子树的信息都已经计算完 ...
- [LOJ 6031]「雅礼集训 2017 Day1」字符串
[LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...
- [LOJ 6030]「雅礼集训 2017 Day1」矩阵
[LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...
- [LOJ 6029]「雅礼集训 2017 Day1」市场
[LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...
- 「LOJ#10051」「一本通 2.3 例 3」Nikitosh 和异或(Trie
题目描述 原题来自:CODECHEF September Challenge 2015 REBXOR 1≤r1<l2≤r2≤N,x⨁yx\bigoplus yx⨁y 表示 ...
- LOJ#10117. 「一本通 4.1 练习 2」简单题
LOJ#10117. 「一本通 4.1 练习 2」简单题 题目描述 题目来源:$CQOI 2006$ 有一个$n$个元素的数组,每个元素初始均为$0$.有$m$条指令,要么让其中一段连续序列数字反转— ...
随机推荐
- Tomcat权威指南-读书摘要系列10
Tomcat集群 一些集群技术 DNS请求分配 TCP网络地址转换请求分配 Mod_proxy_balance负载均衡与故障复原 JDBC请求分布与故障复原
- 2018年9月28日CCPC秦皇岛站参赛总结
day1: 被中间结果超出int范围给叉了,立刻意识到了自己的弱小以及校赛出题的时候是怎么叉别人的 day2: 签到签了40分钟,谨慎一些还是很好的,机子重启耽误了一些时间 一道暴力+LCS的简单题被 ...
- 为ASP.NET控件加入快捷菜单
ContextMenu Control 快捷菜单控件概述: MSDN Liabrary 中包含了几个DHTML快捷菜单的示例.分别提供了对这一功能的不能实现方法.一个快捷菜单就是在页面中任何位置的一组 ...
- Android手机间无线互传功能探索及实现
年前研究了一下Android如何实现无线互传的功能,写了个小demo,最近无事,遂整理一下,与各位共享.前期调研发现,Android想要实现无线互传有以下几种技术:1,Bluetooth通行已久,简单 ...
- Integer中1000==1000为false而100==100为true
查看Integer.java类,会发现有一个内部私有类,IntegerCache.java,它缓存了从-128到127之间的所有的整数对象.如果在这个区间内,他就会把变量当做一个变量,放到内存中:但如 ...
- git与代码托管工具
1.git初识 git是一个版本管理工具,用来管理项目的不同的版本,记录下不同的提交记录,git还可以构建不同的分支,用来给不同的人来推送使用. 推荐的git教程:https://www.cnblog ...
- 3.微信公众号开发:配置与微信公众平台服务器交互的URL接口地址
微信开发基本原理: 1.首先有3个对象 分别是微信用户端 微信公众平台服务器 开发者服务器(也就是放自己代码的服务器) 三者间互相交互 2.微信公众平台服务器 充当中间者角色 (以被动回复消息为例) ...
- vim助手
移动光标 hjkl 2w 向前移动两个单词 3e 向前移动到第 3 个单词的末尾 0 移动到行首 $ 当前行的末尾 gg 文件第一行 G 文件最后一行 行号+G 指定行 <ctrl>+o ...
- 001_关于选中的磁盘具有MBR分区表。在 EFI 系统上,Windows 只能安装到 GPT 磁盘。问题解决
问题: 今天我的diy电脑重装系统时,遇到了一个棘手的问题.在选择安装分区的时候,提示有这样的错误. Windows 无法安装到这个磁盘.选中的磁盘具有MBR分区表.在 EFI 系统上,Windows ...
- java 遍历指定目录下的文件夹并查找包含指定关键字的文件
输入指定关键字,在制定目录中查找包含关键字的文件,返回包含指定关键字的文件路径. package net.xsoftlab.baike; import java.io.File; import jav ...