Description

Input

第一行,两个正整数 S 和 q,q 表示询问数量。
接下来 q 行,每行一个正整数 n。

Output

输出共 q 行,分别为每个询问的答案。

Sample Input

30 3
9
29
1000000000000000000

Sample Output

0
9
450000036

Hint

感谢the Loser协助更正数据
对于100%的数据,2<=S<=2e6​​,1<=n<=101810^{18}10​18​​,1<=q<=10510^510​5​​

好题!

10%算法:

对于S为平方数的倍数时,输出T个0

证明:无论用什么素数去lcm,结果都不可能是平方数

20%算法:

对于输入的n,因为每个素数至少出现一次(否则lcm凑不到),所以需要改动

S数据规模可以看出,素数的数量不会超过7个,即背包的物品少于7个

我们只需要把n减去所有的素数,就相当于先把每个物品都选了一遍

剩下的就是普通背包,不再讲解。(需要结合上一个10%的算法)

100%算法:

n很大,S还可以,物品种数也很少,它们的lcm也在可接受范围之内。

我颓的唯一一句题解:

"n很大,我们考虑一种合法方案,每个ci都不小,而p又是s的约数,我们尝试给ci%=s/pi"

然后就像明白了,受了这个启发后就在自己能力范围之内了

想一下为什么要模,因为我们可以发现每当取的物品数到达s/pi时,那么总量就到达了s,对于每个物品都是这样

那么,对于n,可以把它划分成n=as+c,我们把凑满s的部分叫做一个块

每一个块都可能是被每一个素数凑成的,所以如果有a个块,那么只考虑这些块,总的方案数是多少?

比较容易想到挡板法,可是不太一样:

挡板法用于n个相同物品分成k组,每组至少一件,答案是C(n-1,k-1)

可是我们需要的是n物品k组,每一组至少0件,那么和从背包每个必装一种而使n减掉每种物品相似,我们把物品增加k件从而保证每组都有

那么就是C(n+k-1,k-1)了

至于组合数怎么算。。。因为k-1很小,暴力就好,处理出逆元,n+k-1那部分暴力乘

但是要注意,因为那个部分太大,在乘之前就要取一次模,不然爆LL

好的我们现在处理完了整块的部分,接下来来考虑零散部分(零散部分已不含整块)

显然零散部分没有整块的话它的大小不会很大,最多就是素数个数乘以lcm,1.4e7,可以接受,背包解决

但是,我们怎么保证每个物品都不会凑成一个整块呢?

那么就有了个数限制,它不再是完全背包,而是多重背包

怎么办?其实这么想就偏了

考虑对于dp[m],如果它已经含有整块了,那么去掉这个整块的部分有几种方案,减去不就好了么?

即dp[m]-=dp[m-s];那么就搞定了个数限制的问题,它还是个完全背包

 for(int j=;j<=cntp;++j){
for(int i=;i+p[j]<=maxn;++i)
if(bp[i])bp[i+p[j]]=(bp[i]+bp[i+p[j]])%mod;
for(int i=maxn;i>=;--i)
if(i+ss<=maxn)bp[i+ss]=(bp[i+ss]-bp[i]+mod)%mod;
}

背包部分代码

那么就没什么问题了,最后再说一句n=as+c的分解不是简单的取模,c那个部分可以大于s

因为用k个物品,每个物品的贡献都不到s,但是它们能凑出的最大值接近于ks

多枚举几轮就好啦

 /*
我颓了题解的第一句话,这题我水了
"n很大,我们考虑一种合法方案,每个ci都不小,而p又是s的约数,我们尝试给ci%=s/pi"
然后就不需要在往下看了。
*/
#include<cstdio>
#define mod 1000000007
#define int long long
int s,t,p[],cntp,bp[],maxn,tot,th[],bj[],ths,invv[],inv[];int n;
inline int max(int a,int b){return a>b?a:b;}
main(){
scanf("%lld%lld",&s,&t);int ss=s;
for(int i=;i*i<=s;++i)if(s%i==){
if(s/i%i==){
for(int i=;i<=t;++i)puts("");
return ;
}
p[++cntp]=i;s/=i;tot+=i;
}
if(s!=)p[++cntp]=s,tot+=s;maxn=cntp*ss;
bp[]=;
for(int j=;j<=cntp;++j){
for(int i=;i+p[j]<=maxn;++i)
if(bp[i])bp[i+p[j]]=(bp[i]+bp[i+p[j]])%mod;
for(int i=maxn;i>=;--i)
if(i+ss<=maxn)bp[i+ss]=(bp[i+ss]-bp[i]+mod)%mod;
}
inv[]=invv[]=inv[]=;for(int i=;i<=;++i)invv[i]=(mod+(-(mod/i)*invv[mod%i]%mod))%mod,inv[i]=inv[i-]*invv[i]%mod;
while(t--){
scanf("%lld",&n);n-=tot;
if(n<){puts("");continue;}
if(n<ss){printf("%lld\n",bp[n]);continue;}
int tms=n/ss,ans=;
for(int i=max(,tms-cntp+);i<=tms;++i){
int tans=inv[cntp-]*bp[n-i*ss]%mod;
for(int j=;j<cntp-;++j)tans=tans*((i-+cntp-j)%mod)%mod;
ans=(ans+tans)%mod;
}
printf("%lld\n",ans);
}
}

Finally Accept

DZY Loves Math II:多重背包dp+组合数的更多相关文章

  1. bzoj 3462: DZY Loves Math II

    3462: DZY Loves Math II Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 211  Solved: 103[Submit][Sta ...

  2. BZOJ3462 DZY Loves Math II 【多重背包 + 组合数】

    题目 输入格式 第一行,两个正整数 S 和 q,q 表示询问数量. 接下来 q 行,每行一个正整数 n. 输出格式 输出共 q 行,分别为每个询问的答案. 输入样例 30 3 9 29 1000000 ...

  3. [bzoj3462]DZY Loves Math II (美妙数学+背包dp)

    Description Input 第一行,两个正整数 S 和 q,q 表示询问数量. 接下来 q 行,每行一个正整数 n. Output 输出共 q 行,分别为每个询问的答案. Sample Inp ...

  4. BZOJ3462 DZY Loves Math II(动态规划+组合数学)

    容易发现这是一个有各种玄妙性质的完全背包计数. 对于每个质数,将其选取个数写成ax+b的形式,其中x=S/pi,0<b<x.那么可以枚举b的部分提供了多少贡献,多重背包计算,a的部分直接组 ...

  5. DZY Loves Math II

    简要题面 对于正整数 \(S, n\),求满足如下条件的素数数列 \((p_1,p_2,\cdots,p_k)\)(\(k\) 为任意正整数) 的个数: \(p_1\le p_2\le\cdots\l ...

  6. BZOJ 3462 DZY Loves Math II ——动态规划 组合数

    好题. 首先发现$p$是互质的数. 然后我们要求$\sum_{i=1}^{k} pi*xi=n$的方案数. 然后由于$p$不相同,可以而$S$比较小,都是$S$的质因数 可以考虑围绕$S$进行动态规划 ...

  7. bzoj3462: DZY Loves Math II

    状态很差脑子不清醒了,柿子一直在推错.... ... 不难发现这个题实际上是一个完全背包 问题在于n太大了,相应的有质数的数量不会超过7个 假设要求sigema(1~plen)i pi*ci=n 的方 ...

  8. [BZOJ] DZY Loves Math 系列 I && II

    为了让自己看起来有点事干 ,做个套题吧..不然老是东翻翻西翻翻也不知道在干嘛... \(\bf 3309: DZY \ Loves \ Math\) 令 \(h=f*\mu\) 很明显题目要求的就是\ ...

  9. DZY Loves Math系列

    link 好久没写数学题了,再这样下去吃枣药丸啊. 找一套应该还比较有意思的数学题来做. [bzoj3309]DZY Loves Math 简单推一下. \[\sum_{i=1}^n\sum_{j=1 ...

随机推荐

  1. Thinkphp5.0第一篇

    THINKphp5.0框架 mvc moudle(数据)+view(表现层)+controller(业务逻辑) thinkphp5.0特点 中国人开发最符合国人习惯和思维方式 开源免费面向对象轻量级的 ...

  2. [WP8.1]RSA 使用BouncyCastle 公钥解密

    写应用的时候遇到个服务器返回私钥加密过的数据 ,然后要在客户端用公钥解密的需求 ,一直没找到方法,应用搁置了一个学期,多方搜索,结论就是.net没有实现公钥解密的方法,要自己实现,于是硬着头皮开始看  ...

  3. Scala 数组和List

    Scala 数组和List: import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.Buffer ob ...

  4. Java集合总结—再也不怕面试问到集合了

    Java集合总结 1.常见的集合 Map接口和Collection接口是所有集合框架的父接口: Collection接口的子接口包括:Set接口和List接口 Map接口的实现类主要有:HashMap ...

  5. File类&递归

    File类1.什么是file类Java中处理操作系统文件的类.2.file思想创建一个File对象,代表了操作系统的具体的一个文件(文件,文件夹)然后通过这个File对象就可以操作该文件:删除该文件, ...

  6. 零基础转行web前端,要学习多久?需要掌握些什么?

    web前端开发技术人才越来越吃香,而且web前端领域划分越来越细,对技术的需求越来越高,想学习web前端的人也是越来越多.那么,如何学习web前端知识?从哪开始?转型成为web前端工程师需要学些什么? ...

  7. 小白学 Python(4):变量基础操作

    人生苦短,我选Python 引言 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 前面的文章中,我们介绍了 ...

  8. epoll(2) 源码分析

    epoll(2) 源码分析 文本内核代码取自 5.0.18 版本,和上一篇文章中的版本不同是因为另一个电脑出了问题,但是总体差异不大. 引子留下的问题 关键数据结构 提供的系统调用 就绪事件相关逻辑 ...

  9. windows设置本地域名解析

    1.首先找到host文件:C:\Windows\System32\drivers\etc 2.打开host文件: # Copyright (c) 1993-2009 Microsoft Corp. # ...

  10. Linux常用命令及示例(全)

    NO 分类 PS1 命令名 用法及参数 功能注解1 显示目录信息 # ls ls -a 列出当前目录下的所有文件,包括以.头的隐含文件 # ls ls -l或ll 列出当前目录下文件的详细信息 # l ...