hdu 4651&hdu 4658
2015-07-20 10:58
232 查看
整数拆分
题目描述:
n~1e5(1) 把n拆分成小于等于n的数的和,问有多少种拆分方法
(2) 把n拆分成小于等于n的数的和, 并且相同数字的使用个数小于k个.
题解:
首先是这道题目的解决方法:比如1+1+1+2+3+3. 其实可以写成3个1,1个2,2个3,用母函数写就是
(1+x+x^2…)(1+x^2+x^4…)(1+x^3+x^6….)…..代表每个数用了几个最高项小于等于n/i.之后用等比公式(1/(1-x^k)) k从1到无穷.
然后分母是一个欧拉函数,记为Q(x),那么Q(x)可以o(1)的得到次数和系数.
0 1 -1 2 -2 3 -3 4 -4 (下标)
0 1 2 5 7 12 15 22 26(次数)
次数=(3*i*i-i)/2
系数=(-1)^(i)
有了这个,之后是求多项式的倒数.P(x)和Q(x)相乘是1.因此:
P(n)=P(n-1)+P(n-2)-P(n-5)-P(n-7)…..
P(0) = 1;
这样就可以几乎是sqrt(n)n的dp得到.
其次是(2)的解决方法.
修改母函数,本来是加到正无穷,但是有了k的限制,因此每一个加到(x^i)^k-1 就停止了,因此等比公式的分子上面有一个(1-x^i^k),其实就是Q(x^k)/Q(x).也就是上一道题目的P(x)*Q(x^k).根据给出的k,我们仍然o(1
)的能够算出Q(x^k)的系数.合成一下新的n的系数就行了.
重点:
(1)这两道题目的解法:首先变成几个1,几个2的那种,然后写出母函数.根据要求写母函数.之后化成根欧拉函数Q(x)有关的,利用Q(x)的通项公式来算.(2)整数拆分的性质:
第一.如果每个数不重复,那么用dp可以算.
第二. 如果可以开两维,那么dp中含有个数也可以算. (n,num)=(n-num,num)+(n,num-1)
第三.用<=k的数来拆分等价于用<=k个数来拆分.进一步,等价于n+k拆分成恰好k个数的个数.
第四.将n表达成奇数之和的方法等于两两个数不同.
代码:
const int MOD = 1e9+7; int dp[100010]; void init()//构造出P(x) { memset(dp,0,sizeof(dp)); dp[0] = 1; for(int i = 1;i <= 100000;i++) { for(int j = 1, r = 1; i - (3 * j * j - j) / 2 >= 0; j++, r *= -1) { dp[i] += dp[i -(3 * j * j - j) / 2] * r; dp[i] %= MOD; dp[i] = (dp[i]+MOD)%MOD; if( i - (3 * j * j + j) / 2 >= 0 ) { dp[i] += dp[i - (3 * j * j + j) / 2] * r; dp[i] %= MOD; dp[i] = (dp[i]+MOD)%MOD; } } } } int solve(int n,int k)//构造出Q(x^k) { int ans = dp ; for(int j = 1, r = -1; n - k*(3 * j * j - j) / 2 >= 0; j++, r *= -1) { ans += dp[n -k*(3 * j * j - j) / 2] * r; ans %= MOD; ans = (ans+MOD)%MOD; if( n - k*(3 * j * j + j) / 2 >= 0 ) { ans += dp[n - k*(3 * j * j + j) / 2] * r; ans %= MOD; ans = (ans+MOD)%MOD; } } return ans; }
相关文章推荐
- 【来日复制粘贴】提取工作表和工作簿名称
- oracle 相关语句
- 【Record】ART:Android RunTime
- jquery实现radio按纽全不选和checkbox全选的实例
- VM11安装Mac OS X 10.10
- Android NDK编程问题
- Agri-Net - poj 1258 (Prim 算法)
- Javascript笔记
- DRBD故障分类和恢复办法
- css选择器
- zabbix监控系统的实际应用(原理-安装篇)
- 获取证书扩展域信息
- Mongodb持久化--journal探究(一)
- JAVA常用类之——Math和Random
- 社説 20150720 自衛隊共同訓練 安保法制と連動して拡充せよ
- mysql学习笔记之mysql数据库的安装
- Select For Update 语句浅析
- Java Web乱码分析及解决方案(一)——GET请求乱码
- VC2010和OpenCV2.4.9中imread这个函数不能正确读入图片的解决
- Activity开机画面延迟启动