DZY Loves Math II:多重背包dp+组合数

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];那么就搞定了个数限制的问题,它还是个完全背包

1 for(int j=1;j<=cntp;++j){
2         for(int i=0;i+p[j]<=maxn;++i)
3             if(bp[i])bp[i+p[j]]=(bp[i]+bp[i+p[j]])%mod;
4         for(int i=maxn;i>=0;--i)
5             if(i+ss<=maxn)bp[i+ss]=(bp[i+ss]-bp[i]+mod)%mod;
6     }

背包部分代码

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

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

多枚举几轮就好啦

 1 /*
 2 我颓了题解的第一句话,这题我水了
 3 "n很大,我们考虑一种合法方案,每个ci都不小,而p又是s的约数,我们尝试给ci%=s/pi"
 4 然后就不需要在往下看了。
 5 */
 6 #include<cstdio>
 7 #define mod 1000000007
 8 #define int long long
 9 int s,t,p[11],cntp,bp[14000005],maxn,tot,th[202],bj[202],ths,invv[8],inv[8];int n;
10 inline int max(int a,int b){return a>b?a:b;}
11 main(){
12     scanf("%lld%lld",&s,&t);int ss=s;
13     for(int i=2;i*i<=s;++i)if(s%i==0){
14         if(s/i%i==0){
15             for(int i=1;i<=t;++i)puts("0");
16             return 0;
17         }
18         p[++cntp]=i;s/=i;tot+=i;
19     }
20     if(s!=1)p[++cntp]=s,tot+=s;maxn=cntp*ss;
21     bp[0]=1;
22     for(int j=1;j<=cntp;++j){
23         for(int i=0;i+p[j]<=maxn;++i)
24             if(bp[i])bp[i+p[j]]=(bp[i]+bp[i+p[j]])%mod;
25         for(int i=maxn;i>=0;--i)
26             if(i+ss<=maxn)bp[i+ss]=(bp[i+ss]-bp[i]+mod)%mod;
27     }
28     inv[0]=invv[1]=inv[1]=1;for(int i=2;i<=7;++i)invv[i]=(mod+(-(mod/i)*invv[mod%i]%mod))%mod,inv[i]=inv[i-1]*invv[i]%mod;
29     while(t--){
30         scanf("%lld",&n);n-=tot;
31         if(n<0){puts("0");continue;}
32         if(n<ss){printf("%lld\n",bp[n]);continue;}
33         int tms=n/ss,ans=0;
34         for(int i=max(0,tms-cntp+1);i<=tms;++i){
35             int tans=inv[cntp-1]*bp[n-i*ss]%mod;
36             for(int j=0;j<cntp-1;++j)tans=tans*((i-1+cntp-j)%mod)%mod;
37             ans=(ans+tans)%mod;
38         }
39         printf("%lld\n",ans);
40     }
41 }

Finally Accept

原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11131047.html

时间: 2024-10-12 11:57:35

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

【BZOJ】3309: DZY Loves Math 莫比乌斯反演优化

3309: DZY Loves Math Description 对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample In

[BZOJ3568]DZY Loves Math VII

本人BZOJ的处女作. 这题题面还是蛮有趣的吧. 然后三个问题都蛮有意思的. 要保证正确性,出数据还是异常蛋疼啊. 本来各出三题的.但是考虑到是OJ上的题,就搞在一起了.这样代码量就会比较大. [BZOJ3568]DZY Loves Math VII,布布扣,bubuko.com

【BZOJ 3560】 3560: DZY Loves Math V (欧拉函数)

3560: DZY Loves Math V Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 241  Solved: 133 Description 给定n个正整数a1,a2,-,an,求 的值(答案模10^9+7). Input 第一行一个正整数n. 接下来n行,每行一个正整数,分别为a1,a2,-,an. Output 仅一行答案. Sample Input 3 6 10 15 Sample Output 1595 HINT 1<=n<=1

【BZOJ3563/3569】DZY Loves Chinese II 线性基神题

[BZOJ3563/3569]DZY Loves Chinese II Description 神校XJ之学霸兮,Dzy皇考曰JC. 摄提贞于孟陬兮,惟庚寅Dzy以降. 纷Dzy既有此内美兮,又重之以修能. 遂降临于OI界,欲以神力而凌♂辱众生. 今Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边. 时而Dzy狂WA而怒发冲冠,神力外溢,遂有K条膴蠁边灰飞烟灭. 而后俟其日A50题则又令其复原.(可视为立即复原) 然若有祭坛无法相互到达,Dzy之神力便会大减,于是欲知其是否连通. Input 第

[BZOJ3569]DZY Loves Chinese II(随机化+线性基)

3569: DZY Loves Chinese II Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1515  Solved: 569[Submit][Status][Discuss] Description 神校XJ之学霸兮,Dzy皇考曰JC. 摄提贞于孟陬兮,惟庚寅Dzy以降. 纷Dzy既有此内美兮,又重之以修能. 遂降临于OI界,欲以神力而凌♂辱众生. 今Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边. 时而Dzy狂WA而怒发冲冠,神力外溢,

bzoj 3569: DZY Loves Chinese II

链接 3569: DZY Loves Chinese II 题目大意:给出一张\(n\)个点\(m\)条边的无向图,进行\(q\)次询问,问删掉某\(k\)条边后图是否联通,强制在线. \(N≤100000 \ M≤500000\ Q≤50000\ 1≤K≤15\) 先考虑一下离线怎么做: \(cdq\)分治. 首先把所有没有影响的边都建出来 分治过程: 1.把左边没有右边有的边建出来 2.分治左边 3.把并查集恢复至初始的样子 4.把右边没有左边有的边建出来 5.分治右边 虽然每次\(cdq\

bzoj 3309 DZY Loves Math

LINK:DZY Loves Math 一道比较有意思的数论题 原谅我的智障多调了40min. 可以简单的推式子推出 答案为\(\sum{w=1}^n\frac{n}{w}\frac{m}{w}\sum{x|w}\mu(x)f(\frac{w}{x})\) f函数定义和题目中一致. 考虑后面前缀和怎么求 发现光求f(x)复杂度都比较高.如果我们把f(x)求出再调和级数预处理 那得GG 1e7过不了log+根号 考虑考虑一下\(\mu\)和f的这种形式肯定值有局限 设后面的东西为g(x) 不难发现

POJ 1742 Coins 【多重背包DP】

题意:有n种面额的硬币.面额.个数分别为A_i.C_i,求最多能搭配出几种不超过m的金额? 思路:dp[j]就是总数为j的价值是否已经有了这种方法,如果现在没有,那么我们就一个个硬币去尝试直到有,这种价值方法有了的话,那么就是总方法数加1.多重背包可行性问题 传统多重背包三重循环会超时,因为只考虑是否可行,没有考虑剩余面额数量的因素. o(n*v)方法 #include <iostream> #include <cstdio> #include <string.h> #

【bzoj1531】[POI2005]Bank notes 多重背包dp

题目描述 Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有n种面值的硬币,面值分别为b1, b2,..., bn. 但是每种硬币有数量限制,现在我们想要凑出面值k求最少要用多少个硬币. 输入 第一行一个数 n, 1 <= n <= 200. 接下来一行 n 个整数b1, b2,..., bn, 1 <= b1 < b2 < ... < b n <= 20 000, 第三行 n 个整数c1, c2,..., cn, 1 <