Description
Input
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}1018,1<=q<=10510^5105
好题!
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 }