紫色百合
来源:互联网 发布:ubuntu 杀死僵尸进程 编辑:程序博客网 时间:2024/04/27 13:30
https://nanti.jisuanke.com/t/16619
稍稍运用一下数学知识发现题目要求的是选出的集合每个元素+1之后的乘积等于2^P的方案数,取个log就变成了↓
在1~N选若干个数使得总和等于P,求方案数
证明:
设集合S的价值为f(S),当n=2时,设选了i和j号百合,集合S为{2^i-1,2^j-1}, f(S)=1(空集)+(2^i-1)+(2^j-1)+(2^i-1)*(2^j-1)=2^(i+j)
由递推关系
变形得
证毕。
然后用普通的背包DP可以就拿到60分了
然后我们发现,由于物品大小是1~N,所以最多选取O(sqrt(P))个物品,背包就满了
满分做法可以用状态f[i][j]表示选i个物品,占容量为j的方案数
由于每个背包是不同的,所以根据已选的最小的物品分类讨论一下:
如果最小的物品是1,相当于i-1个物品凑出了j-i的大小,然后整体+1
如果最小的物品不是1,相当于i个物品凑出了j-i的大小,然后整体+1
需要注意我们要防止出现选择了大小为N+1的物品的情况,所以需要减去
得到递推式f[i][j]=f[i-1][j-i]+f[i][j-i]-f[i-1][j-(N+1)]
这个算法的精髓是巧妙地利用了所有物品的价值取遍了{1,...,n}中的所有自然数。
时间复杂度O(Nsqrt(N))
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int mod=998244353;int f[450][100010];int main(){int n,p;scanf("%d%d",&n,&p);int i,j,ans=0;f[0][0]=1;for(i=1;(i+1)*i/2<=p;i++){for(j=i;j<=p;j++){f[i][j]=f[i-1][j-i]+f[i][j-i];if(j>=(n+1)) f[i][j]-=f[i-1][j-(n+1)];if(f[i][j]<0) f[i][j]+=mod;if(f[i][j]>=mod) f[i][j]-=mod;}ans+=f[i][p];if(ans>=mod) ans-=mod;}printf("%d",ans);}
阅读全文
0 0
- 紫色百合
- [DP] 计蒜客 2017 NOIP模拟赛(二)Day2 T2.紫色百合
- 百合
- 紫色浪漫
- 冬日百合
- 百合死了
- 茉莉百合
- 香水百合
- 庇里牛斯百合
- 紫色魅影
- 紫色手环
- 半透明绚丽紫色字体
- 美丽的紫色
- vijos 紫色的手链
- 我爱百合
- 小百合史记
- 写给小百合
- 破碎的百合
- jsp,Servlet常见题目
- Spring源码分析(一)
- JSP的内置对象二
- HDU 1829 A Bug's Life
- 除法取模与逆元/费马小定理
- 紫色百合
- 操作系统之处理机调度
- 解决mysql中文乱码无法插入ERROR 1366
- 面向对象的编程练习
- python numpy 学习笔记(10)
- CentOS6.5手动安装glibc-2.14后locale出现No such file or directory终极解决办法
- 分享一个验证码类
- php正则提取文本中多个11位国内手机号完整实例
- OC中常用宏