数位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即可。
相关推荐
yaoh.wang9 小时前
力扣(LeetCode) 13: 罗马数字转整数 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·跳槽
T1ssy9 小时前
布隆过滤器:用概率换空间的奇妙数据结构
算法·哈希算法
hetao173383710 小时前
2025-12-12~14 hetao1733837的刷题笔记
数据结构·c++·笔记·算法
鲨莎分不晴10 小时前
强化学习第五课 —— A2C & A3C:并行化是如何杀死经验回放
网络·算法·机器学习
搞科研的小刘选手11 小时前
【ISSN/ISBN双刊号】第三届电力电子与人工智能国际学术会议(PEAI 2026)
图像处理·人工智能·算法·电力电子·学术会议
拉姆哥的小屋11 小时前
从混沌到秩序:条件扩散模型在图像转换中的哲学与技术革命
人工智能·算法·机器学习
Sammyyyyy11 小时前
DeepSeek v3.2 正式发布,对标 GPT-5
开发语言·人工智能·gpt·算法·servbay
sin_hielo12 小时前
leetcode 2110
数据结构·算法·leetcode
Jay200211112 小时前
【机器学习】33 强化学习 - 连续状态空间(DQN算法)
人工智能·算法·机器学习
panzer_maus12 小时前
归并排序的简单介绍
java·数据结构·算法