题目传送门

题目大意

给出 \(n\),第 \(i\) 个数有 \(i\) 个,问凑出 \(n\) 的方案数。

\(n\le 10^5\)

思路

呜呜呜,傻掉了。。。

首先想到根号分治,分别考虑 \([1,\sqrt n]\) 以及 \([\sqrt n+1,n]\)。

  1. \([1,\sqrt n]\)

不难看出这部分可以直接 dp,设 \(f_{i,j}\) 为前面 \(i\) 种物品选出重量为 \(j\) 的方案数,可以得到转移式:

\[f_{i,j}=f_{i-1,j}+f_{i,j-i}-f_{i-1,j-i\times (i+1)}
\]
  1. \([\sqrt n+1,n]\)

不难看出这部分最多选出 \(\sqrt n\) 个物品,于是可以设 \(g_{i,j}\) 表示选了 \(i\) 物品,选出重量为 \(j\) 的方案数。可以得到转移式:

\[g_{i,j}=g_{i,j-i}+g_{i,j-\sqrt n-1}
\]

具体含义就是转移有两种,第一种就是集体右移,即重量为 \(k\) 的都变为 \(k+1\),另外一种就是选 \(\sqrt n+1\)。


综上时空复杂度 \(\Theta(n\log n)\),第一种记得滚动数组,不然会 MLE。

\(\texttt{Code}\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define Int register int
  4. #define mod 23333333
  5. #define MAXN 100005
  6. #define MAXM 325
  7. template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
  8. template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
  9. template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
  10. int n,sqr;
  11. int f[2][MAXN],g[MAXM][MAXN],f1[MAXN],f2[MAXN];
  12. /*
  13. f[i][j] 表示前面i个物品选出重量j的方案数,g[i][j]表示i个物品选出重量j的方案数
  14. f[i][j]=f[i-1][j]+f[i][j-i]-f[i-1][j-i*(i+1)]
  15. g[i][j]=g[i][j-i]+g[i-1][j-sqr-1]
  16. */
  17. int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
  18. int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
  19. void Work1 (){
  20. f[0][0] = 1;
  21. for (Int i = 1;i <= sqr;++ i)
  22. for (Int j = 0;j <= n;++ j)
  23. f[i & 1][j] = add (f[i - 1 & 1][j],dec (j >= i ? f[i & 1][j - i] : 0,j >= i * (i + 1) ? f[i - 1 & 1][j - i * (i + 1)] : 0));
  24. for (Int i = 0;i <= n;++ i) f1[i] = f[sqr & 1][i];
  25. }
  26. void Work2 (){
  27. g[0][0] = 1;
  28. for (Int i = 1;i <= sqr;++ i)
  29. for (Int j = 0;j <= n;++ j)
  30. g[i][j] = add (j >= i ? g[i][j - i] : 0,j >= sqr + 1 ? g[i - 1][j - sqr - 1] : 0);
  31. for (Int i = 0;i <= n;++ i)
  32. for (Int j = 0;j <= sqr;++ j) f2[i] = add (f2[i],g[j][i]);
  33. }
  34. signed main(){
  35. read (n),sqr = sqrt (n),Work1(),Work2 ();
  36. int ans = 0;for (Int i = 0;i <= n;++ i) ans = add (ans,1ll * f1[i] * f2[n - i] % mod);
  37. write (ans),putchar ('\n');
  38. return 0;
  39. }

题解 51nod 1597 有限背包计数问题的更多相关文章

  1. 51nod 1597 有限背包计数问题 (背包 分块)

    题意 题目链接 Sol 不会做啊AAA.. 暴力上肯定是不行的,考虑根号分组 设\(m = \sqrt{n}\) 对于前\(m\)个直接暴力,利用单调队列优化多重背包的思想,按\(\% i\)分组一下 ...

  2. 51Nod 有限背包计数问题 题解报告

    首先这道题理论上是可以做到O(nlogn)的,因为OEIS上有一个明显可以用多项式乘法加速的式子 但是由于模数不是很兹磁,所以导致nlogn很难写 在这里说一下O(n*sqrt(n))的做法 首先我们 ...

  3. 51Nod1957 有限背包计数问题

    传送门 另一个传送门 这题还挺有意思…… 先贴一波出题人的题解…… (啥你说你看不见?看来你还没过啊,等着A了再看或者乖乖花点头盾好了……) 然后是我的做法……思想都是一样的,只是细节不一样而已…… ...

  4. [51nod1597]有限背包计数问题

    你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少 两种方案不同当且仅当存在至少一个数i满足第i种物品使用的数量不同 Input 第一行一个正整数n 1 ...

  5. 2018.09.25 51nod1597 有限背包计数问题(背包+前缀和优化)

    传送门 dp好题. 我认为原题的描述已经很清楚了: 你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少. 两种方案不同当且仅当存在至少一个数i满足第i种 ...

  6. 【LOJ6089】小Y的背包计数问题(动态规划)

    [LOJ6089]小Y的背包计数问题(动态规划) 题面 LOJ 题解 神仙题啊. 我们分开考虑不同的物品,按照编号与\(\sqrt n\)的关系分类. 第一类:\(i\le \sqrt n\) 即需要 ...

  7. LOJ #6089. 小 Y 的背包计数问题

    LOJ #6089. 小 Y 的背包计数问题 神仙题啊orz. 首先把数分成\(<=\sqrt n\)的和\(>\sqrt n\)的两部分. \(>\sqrt n\)的部分因为最多选 ...

  8. LOJ#6089 小 Y 的背包计数问题 - DP精题

    题面 题解 (本篇文章深度剖析,若想尽快做出题的看官可以参考知名博主某C202044zxy的这篇题解:https://blog.csdn.net/C202044zxy/article/details/ ...

  9. LOJ6089 小Y的背包计数问题(根号优化背包)

    Solutioon 这道题利用根号分治可以把复杂度降到n根号n级别. 我们发现当物品体积大与根号n时,就是一个完全背包,换句话说就是没有了个数限制. 进一步我们发现,这个背包最多只能放根号n个物品. ...

随机推荐

  1. Win7/Win10+VS2017+OpenCV3.4.2安装、测试

    安装VS2017 在微软官网https://www.microsoft.com,下载Visual Studio 2017安装包 用管理员权限运行vs2017 enterprise安装包,安装过程会持续 ...

  2. 浅谈Java和Go的程序退出

    前言 今天在开发中对Java程序的退出产生了困惑,因为题主之前写过一段时间Go,这两者的程序退出逻辑是不同的,下面首先给出结论,再通过简单的例子来介绍. 对于Java程序,Main线程退出,如果当前存 ...

  3. Spring笔记(2)

    一.AOP简介 1.概念: 面向切面编程(Aspect-Oriented Programming),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善. ...

  4. Tomcat中的一些问题

    问题: 一闪而过,解决办法: 用记事本打开startup.bat文件,在最下面添加pause 再次运行,发现问题 CATALINA_HOME是TOMCAT安装路径的别名, 计算机>属性>环 ...

  5. android kotlin 子线程中调用界面UI组件崩溃

    UI 只能在主线程内更新,子线程需要更新UI组件时可以这样: fun fuck(){ Executors.newSingleThreadExecutor().execute{ // url reque ...

  6. 字符串截取子串(Java substring , indexOf)

    前言 因为之前java课设做的是股票分析系统,我找的接口返回的是一个.csv文件,因为这种文件里面的数据是以逗号分隔的,所以要对数据进行分析的时候需要截取子串,并且以逗号作为截取的标志.所以接下来就说 ...

  7. js基本数据类型之间的转换

    常见五大基本数据类型 1.number 2.string 3.boolean 4.undefined 5.null 一.转换为string ①调用toString() 方法 因为null和undefi ...

  8. NCNN优化实时面部关键点检测

    效果图 演示手机为红米10X pro,可以实时跑人脸检测+关键点识别二个模型. 主要优化 上次看见有人讨论人脸检测与关键点识别,用的是opencv相关,于是想看下深度神经网络相关部分的进展,先选定了推 ...

  9. awk 命令-随笔

    awk语法: awk [option] 'pattern{action}' file ... awk [参数] '条件{动作}' 文件 ... 解析: 命令: awk 参数: -F "&qu ...

  10. C# Equals方法和==有什么区别

    开发工具:VS2019 一.关于这两个比较,需要从值类型和引用类型两方面来说 (A)先说值类型 上图: 因为在对值类型进行比较时候,不管 .Equals() 方法还是 == 方法,都是对值类型变量(图 ...