数位dp|组合数学|差分emplace

lc2021

差分+sort

  • 事件处理: [start, end+1) ,对应事件为 (start, +1) 和 (end+1, -1) ,排序后遍历事件计算每个位置的亮度

  • 遍历统计:依次用前一个数 累加亮度变化值,即为变化点

实时更新最大亮度和对应位置,保证找到最亮且坐标最小的位置

class Solution {

public:

int brightestPosition(vector<vector<int>>& lights) {

vector<pair<int, int>> events;

for (auto& light : lights) {

int start = light[0] - light[1];

int end = light[0] + light[1] + 1; // 转换为左闭右开区间,方便差分

events.emplace_back(start, 1);

events.emplace_back(end, -1);

}

sort(events.begin(), events.end());

int maxBright = 0, currentBright = 0, ans = 0;

for (auto& [pos, delta] : events) {

currentBright += delta;

if (currentBright > maxBright) {

maxBright = currentBright;

ans = pos;

}

}

return ans;

}

};

emplace_back 适合需要直接在容器内构造对象的场景(可避免临时对象拷贝/移动,提升性能)

push_back 适合传递已有对象(或临时对象会被隐式构造时),逻辑更直观

sum++:需要"原地构造"选 emplace_back ,传递"现成对象"选 push_back++

lc3317

"拆分问题→分别计算各部分→相乘求和"

const int mod = 1e9 + 7;

const int MX = 1001;

long long s[MX][MX];

int init = []()->int {

//i个人分成j组

s[0][0] = 1;

for (int i = 1; i < MX; i++)

{

for (int j = 1; j < MX; j++)

{

s[i][j] = (s[i - 1][j - 1] + (long long)j*s[i - 1][j])%mod;

}

}

return 0;

}();

class Solution {

public:

int numberOfWays(int n, int x, int y) {

long long powY = 1;

long long A = 1;

long long ans = 0;

for (int i = 1; i <= min(n, x); i++)

{

A = (A*(x - i + 1)) % mod;

powY = powY * y%mod;

s[n][i]%=mod;

ans = (ans + ((A * powY)%mod*s[n][i])%mod)%mod;

}

return ans;

}

};

一、问题在问什么

计算**"把 n 个人安排到 x 个节目里,每个节目至少1人,且每个节目有 y 种打分方式"的总方案数**

二、概念:第二类斯特林数

定义: S(n, i) 表示把 n 个不同的元素分成 i 个非空集合(集合无顺序)的方案数。

比如 S(3, 2) 就是把3个人分成2个非空组的方式数,结果是3(比如{1,2}和{3}、{1,3}和{2}、{2,3}和{1})

三、递推公式怎么来

++S(n, i) = S(n-1, i-1) + i * S(n-1, i)++

  • 第一种情况:第 n 个人自己 ++单独成一组++ → 剩下 n-1 个人分成 i-1 组,即 S(n-1, i-1) 。

  • 第二种情况:第 n 个人 ++加入之前++的 i 组中的某一组 → 有 i 种选择,剩下 n-1 个人分成 i 组,即 i * S(n-1, i) 。

四、代码

  1. 预处理斯特林数( init 函数)

s[0][0] = 1; // 0个人分成0组,算1种方案

for (int i = 1; i < MX; i++)

for (int j = 1; j < MX; j++)

++s[i][j] = (s[i-1][j-1] + (long long)j * s[i-1][j]) % mod;++

这部分是提前计算所有可能的 S(n, i) ,存在 s 数组里,方便后面直接用

  1. 计算最终答案( numberOfWays 函数)

我们要枚举"选 i 个节目来安排人",然后把三部分方案数相乘:

  • A :从 x 个节目中选 i 个有顺序的方案数(排列数 A(x, i) = x*(x-1)*...*(x-i+1) )

++- S(n, i) :把 n 个人分成 i 个非空组的方案数(用预处理好的 s 数组)++

  • powY :每个节目有 y 种打分方式, i 个节目就是 y^i 种

最后把所有 i 的情况加起来,就是最终答案。

int numberOfWays(int n, int x, int y) {

long long powY = 1;

long long A = 1;

long long ans = 0;

for (int i = 1; i <= min(n, x); i++) {

A *= (x - i + 1);

powY *= y;

ans += ++A * powY * s[n][i];++

}

return ans;

}

五、举个例子

比如 n=3 , x=2 , y=2 :

  • 当 i=1 :选1个节目,把3人分成1组,打分方式 2^1 → 方案数 A(2,1)*S(3,1)*2^1 = 2*1*2 = 4 。

  • 当 i=2 :选2个节目,把3人分成2组,打分方式 2^2 → 方案数 A(2,2)*S(3,2)*4 = 2*3*4 = 24 。

  • 总答案: 4+24=28

lc600

数位dp

class Solution {

public:

int findIntegers(int n) {

vector<int> digits;

int x = n;

while (x > 0) {

digits.push_back(x % 2);

x /= 2;

}

reverse(digits.begin(), digits.end());

vector<vector<int>> memo(digits.size(), vector<int>(2, -1));

function<int(int, int, bool)> dfs = [&](int pos, int pre, bool isLimit) -> int {

++if (pos == digits.size())
return 1;
++

if (!isLimit && memo[pos][pre] != -1) {

return memo[pos][pre];

}

int up = isLimit ? digits[pos] : 1;

int res = 0;

for (int d = 0; d <= up; d++) {

++bool newLimit = isLimit && (d == up);++

if (pre == 1 && d == 1) {

continue;

}

++res += dfs(pos + 1, d, newLimit);++

}

if (!isLimit) {

memo[pos][pre] = res;

}

return res;

};

return dfs(0, 0, true);

}

};

  • 条件变了:比如"数位和是偶数",就把 pre 改成"前几位的数位和的奇偶性",然后判断最终和是否为偶。

  • 进制变了:比如十进制题目,就把拆数逻辑改成 %10 和 /10 , up 改成9即可。
相关推荐
2301_764441331 小时前
新能源汽车电磁辐射高级预测
python·算法·数学建模·汽车
Keep_Trying_Go1 小时前
论文Leveraging Unlabeled Data for Crowd Counting by Learning to Rank算法详解
人工智能·pytorch·深度学习·算法·人群计数
仟濹1 小时前
【C/C++】经典高精度算法 5道题 加减乘除「复习」
c语言·c++·算法
顾安r2 小时前
11.21 脚本 网页优化
linux·前端·javascript·算法·html
WolfGang0073212 小时前
代码随想录算法训练营Day27 | 56.合并区间、738.单调递增的数字、968.监控二叉树
算法
信奥卷王3 小时前
2025年9月GESPC++三级真题解析(含视频)
开发语言·c++·算法
努力学习的小廉3 小时前
我爱学算法之—— BFS之FLoodFill算法
算法·宽度优先
天选之女wow3 小时前
【Hard——Day8】65.有效数字、68.文本左右对齐、76.最小覆盖子串
linux·运维·redis·算法·leetcode
AI大模型学徒3 小时前
NLP基础(八)_马尔可夫模型
算法·机器学习·自然语言处理·nlp·概率论·马尔可夫模型