图计数

题意

给定 n,m ,求 mNmodP 。其中, P=999999599 N 为将n进行整数拆分的方案数,即将 n 表示成若干个正整数之和的方案数。

n,m200000

Time  Limits:3000ms
Memory  Limits:256M

分析

根据费马小定理, mN=mNmod(P1) ,这个可用快速幂算。我们的问题就是如何求 Nmod(P1)

我们先想 O(N2) 的算法。因为每个正整数都能使用若干次,那么这就是一个完全背包问题。但是本题中此算法的复杂度显然不可接受。

我们把正整数以 N 分界。
那么对于小于等于 N 的正整数,我们直接完全背包,求出用它们组成和为 i 的方案数,记为f[i]。这里的时间复杂度是 O(NN)
对于大于 N 的正整数,可以发现,我们最多只会选择 N 个。记 k=N ,我们考虑这样一个方程:
g[i][j] 为已经选了 i 个数,它们的和为j的方案数。
转移: g[i][j]=g[i1][jk]+g[i][ji]

这个方程是什么意思呢?
我们把每个选择的数 xi 都看成由 k 加上xik 1 达到的。那么一种选择数的方案{xn}序列,把它们从大到小排序,我们可以在加入第一个 k 后,将第一个数加上(x1x2) 1 ;然后加入第二个k,把前两个数加上 (x2x3) 1 ;加入第三个k,把前三个数加上 (x3x4) 1 ……这样做到最后,我们把所有数加上(xnk) 1 ,我们就能得到这个方案。

这样,我们就同样能以O(NN)的时间复杂度求出 g ,然后将f g 合并求出组成和为n的方案数就行了。

注意:求 f g要滚动数组。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值