Problem

CodeChef-IOPC14L

题目概要:给定 \(n\) 种糖果且给定每种糖果的数量 \(A_i\),\(Q\) 组询问,每次问选出 \(S\) 个糖果的方案数(模\(10^9+7\))

\(n\leq 10^6,A_i\leq 10^3,Q\leq 10^4,S\leq 2\times 10^3\)

Solution

都说这题是容斥,但是始终不知道如何容斥,下面介绍一个母函数的做法

这题想暴力首先可以想到将所有糖果的母函数乘起来。形式化的,对于一种糖果若有 \(t\) 个,则其母函数为 \(\sum_{i=0}^tx^i\),将所有共 \(n\) 个母函数乘起来得到的\(x^S\)对应的系数即为答案

问题转化为求所有母函数的积,设为 \(F\)

考虑到 \(n\leq 10^6\),暴力求积复杂度为 \(O(nS\log S)\),但\(A_i\leq 10^3\),则考虑可以将本质相同的糖果合并一下,可以得出 \(s[x]\) 表示有 \(x\) 颗糖果的种类有多少,则

\[F=\prod_{i=1}^{2000}(\sum_{j=0}^ix^j)^{s[i]}
\]

这个东西的复杂度是 \(O(S^2\log S\log n)\) 的,照理说已经比较优了,但还可以继续优化

考虑到

\[\sum_{i=0}^nx^i=\frac {x^{n+1}-1}{x-1}
\]

所以上面的式子可以化为

\[F=\prod_{i=1}^{2000}(\frac {x^{i+1}-1}{x-1})^{s[i]}
\]

\[F=\frac {\prod_{i=1}^{2000}(x^{i+1}-1)^{s[i]}}{(x-1)^n}
\]

上式中的分子由于每一项都是二项式的幂次,最终的答案可以利用Dp在 \(O(AS\ln S)\) 的时间内求得(其中\(\ln S\)为级数求和复杂度)

至于分母,视作 \((x-1)^{-n}\),可以考虑

\[(1-x)^{-1}=\frac 1{1-x}=\sum_{i=0}^{+\infty}x^i
\]

\[(x-1)^{-n}=(-1)^n(1-x)^{-n}=(-1)^n(\frac 1{1-x})^n=(-1)^n(\sum_{i=0}^{+\infty}x^i)^n
\]

发现那个 \((-1)^n\) 很讨厌,于是将原式 \(F\) 的分母分子同时乘一个 \((-1)^n\),由于 \(\sum s[i]=n\),所以分子变为 \(\prod_{i=1}^{2000}(1-x^{i+1})^{s[i]}\),同样可以利用Dp在 \(O(AS\ln S)\) 的时间内求得

继续考虑分母,现在已经求得分母倒数为 \((\sum_{i=0}^{+\infty}x^i)^n\),这个式子中 \(x^k\) 的项系数等价于将 \(k\) 分解为 \(n\) 个非负整数和的方案数,即\(\binom {n+k-1}{k}\)

统计答案只需要分子与分母倒数做卷积即可,时间复杂度 \(O(n+AS\ln S+S^2)\)

Code

另外,这道题不支持c++提交,整的我交了好多次才知道 c 与 c++ 的不同(比如说不能用取址符、不能用 const 定义出的数字去定义数组大小等)

#include <stdio.h>
#include <ctype.h>
typedef long long ll; inline int read(){
char c11=getchar();int x = 0;
while(!isdigit(c11))c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
return x;
} //const int N = 2001, M = 2001000, p = 1000000007;
const int p = 1000000007;
#define N 2001
#define M 2001000
int fac[M],inv[M],s[N];
int f[N][N],Ans[N];
int n; inline int qpow(int A,int B){
int res = 1;while(B){
if(B&1) res = (ll)res * A%p;
A = (ll)A * A%p, B >>= 1;
}return res;
} inline int c(int nn,int mm){return (ll)fac[nn]*inv[mm]%p*inv[nn-mm]%p;} int main() {
fac[0] = f[0][0] = 1;
for(int i=1;i<M;++i) fac[i] = (ll)fac[i-1]*i%p;
inv[M-1] = qpow(fac[M-1],p-2);
for(int i=M-1;i;--i) inv[i-1] = (ll)inv[i]*i%p; n = read();
for(int i=1;i<=n;++i)++s[read()]; for(int i=1;i<N;++i)
for(int j=0,t;j<=s[i] && (t = (i+1)*j)<N;++j)
if(j&1) for(int k=0;k+t<N;++k)
f[i][k+t] = (f[i][k+t] + (ll)c(s[i],j) * f[i-1][k]%p*(p-1))%p;
else for(int k=0;k+t<N;++k)
f[i][k+t] = (f[i][k+t] + (ll)c(s[i],j) * f[i-1][k])%p; for(int i=0;i<N;++i)
s[i] = c(n+i-1,i); for(int i=0;i<N;++i)
for(int j=0;j<=i;++j)
Ans[i] = (Ans[i] + (ll)f[N-1][j] * s[i-j])%p; int Q = read();
while(Q--) printf("%d\n",Ans[read()]);
return 0;
}

题解-CodeChef IOPC14L Sweets Problem的更多相关文章

  1. 【题解】CF45G Prime Problem

    [题解]CF45G Prime Problem 哥德巴赫板子题? \(\frac{n(n+1)}{2}\)若是质数,则不需要分了. 上式 若是奇数,那么拆成2和另一个数. 上式 若是偶数吗,直接\(O ...

  2. 【题解】P4137 Rmq Problem(莫队)

    [题解]P4137 Rmq Problem(莫队) 其实这道题根本就不用离散化! 因为显然有\(mex\)值是\(\le 2\times 10^5\)的,所以对于大于\(2\times 10^5\)的 ...

  3. 题解西电OJ (Problem 1006 - 转盘游戏)--动态规划

    题目链接 : http://acm.xidian.edu.cn/land/problem/detail?problem_id=1006 Description wm最近喜欢上一种无聊的转盘解锁游戏,他 ...

  4. 【题解】An Easy Problem

    题目描述 给定一个正整数N,求最小的.比N大的正整数M,使得M与N的二进制表示中有相同数目的1. 举个例子,假如给定的N为78,其二进制表示为1001110,包含4个1,那么最小的比N大的并且二进制表 ...

  5. [题解]UVA10026 Shoemaker's Problem

    链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&am ...

  6. [题解] [AGC024F] Simple Subsequence Problem

    题目大意 有一个 01 串集合 \(S\),其中每个串的长度都不超过 \(N\),你要求出 \(S\) 中至少是 \(K\) 个串的子序列的最长串,如果有多解,输出字典序最小的那组解. 由于 \(S\ ...

  7. 题解西电OJ (Problem 1007 -做一名正气的西电人 )--长整型计算

    Description 一天,wm和zyf想比比谁比较正气,但正气这种东西无法量化难以比较,为此,他们想出了一个方法,两人各写一个数字,然后转化为二进制,谁的数字中二进制1多谁就比较正气! Input ...

  8. 题解西电OJ (Problem 1005 -跳舞毯)--动态规划

    Description zyf不小心得了一种怪病,为了维持一天的精力他必须不停跳动.于是他买了一条跳舞毯,每天跳上几小时.众所周知,跳舞毯是给定一个序列,让你在指定时间踏指定的按钮,但zyf似乎不怎么 ...

  9. 题解西电OJ (Problem 1004 -亚特兰提斯)--最小生成树

    Description 为了找寻沉睡的亚特兰提斯大陆,wm来到了大西洋上进行探险,找了半个月仍一无所获.然而在一次突袭而来的暴风雨后,wm的船莫名地驶入了一片未知的区域,发现了一个地图上未标记的岛屿, ...

随机推荐

  1. C# 使用微软自带的Speech进行语音输出

    1.在VS中使用微软自带的Speech进行语音播报,首先需要添加引用: 2.具体实现逻辑代码如下:

  2. Set.js--创建无重复值的无序集合

    Set 集合,不同于 Array,是一种没有重复值的集合. 以下代码出自于<JavaScript 权威指南(第六版)>P217,注意:这里并不是指 es6 / es2015 中的 Set ...

  3. 基于密度峰值的聚类(DPCA)

    1.背景介绍 密度峰值算法(Clustering by fast search and find of density peaks)由Alex Rodriguez和Alessandro Laio于20 ...

  4. css3学习系列之移动

    transform功能 放缩 使用sacle方法实现文字或图像的放缩处理,在参数中指定缩放倍率,比如sacle(0.5)表示缩小50%,例子如下: <!DOCTYPE html> < ...

  5. rxjs一句话描述一个操作符(1)

    之前一直在写LINQ之类的东西,对于函数式的面向对象还是有一些功底,所以对于rxjs,感觉上不是很难,但是每次看完过几天就忘,还是记一下笔记吧,好记性不如烂笔头真不是盖的. 首先介绍几个重要的概念. ...

  6. 该错误的解决办法:Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1

    Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1 这个问题,原因是UTF-8编码有可能是两个.三个.四个字节.Emoji表 ...

  7. JavaScript实用的工具/类库

    Moment.js//JavaScript日期处理类库. Lodash.js//非常实用的工具库. MD5//加密. Numeral.js//格式化和数字四则运算. Pure.css//CSS模块.

  8. Sqoop export(Hive to MySQL) 的一些 reference

    之后可能会整理成文章..还有一些坑没趟完. Reference: https://cloud.tencent.com/developer/article/1078473  Sqoop抽取Hive Pa ...

  9. 内存管理中提到的hot cold page

    所谓冷热是针对处理器cache来说的,冷就是页不大可能在cache中,热就是有很大几率在cache中. cold page和hot page的概念可以参考LWN的一片文章http://lwn.net/ ...

  10. Java 常用数据结构对象的实现原理 集合类 List Set Map 哪些线程安全 (美团面试题目)

    Java中的集合包括三大类,它们是Set.List和Map, 它们都处于java.util包中,Set.List和Map都是接口,它们有各自的实现类. List.Set都继承自Collection接口 ...