当前位置: 首页 > news >正文

6.17 note

翻转矩阵的贪心

 //1.行翻转:确保最高位为1
 //2.列反转:  计数,让除最高位外 多数变为1

返回二维空数组

return {};

数学题

const int MOD = 1e9 + 7;

 

class Solution {

  int fast_pow(uint64_t base, int exp) {

    uint64_t result = 1;

    while (exp > 0) {

      if (exp % 2 == 1) {

        result = (result * base) % MOD;

      }

      base = (base * base) % MOD;

      exp /= 2;

    }

    return result;

  }

 

  int comb(int n, int k) {

    if (k > n)

      return 0;

    if (k == 0 || k == n)

      return 1;

 

    uint64_t numerator = 1;

    uint64_t denominator = 1;

    for (int i = 0; i < k; ++i) {

      numerator = (numerator * (n - i)) % MOD;

      denominator = (denominator * (i + 1)) % MOD;

    }

    return (numerator * fast_pow(denominator, MOD - 2)) % MOD;

  }

 

public:

  int countGoodArrays(int n, int m, int k) {

    uint64_t res = m;

    res = ((res * fast_pow(m - 1, n - k - 1)) % MOD) * comb(n - 1, k);

    return res % MOD;

  }

};

 

1. 先看 “全局” 小设定: const int MOD = 1e9 + 7; 

这是给结果 “取模” 用的。因为题目里结果可能很大,得按照题目要求(一般竞赛题会要求对 10^9 + 7 取模)把结果限制在合理范围,避免数值爆炸、也符合题目输出要求。

 

2. 类和方法整体作用

这是一个叫  Solution  的类,里面封装了几个函数,最终用  countGoodArrays  解决 “统计恰好有 K 个相等相邻元素的数组数目” 问题。可以理解成:给定数组长度  n 、数的范围  m (每个位置选 1~m 的数)、需要恰好  k  对相邻相等的情况,计算有多少种这样的数组。

 

3. 逐个函数拆解

(1) fast_pow :快速算 “幂取模”

int fast_pow(uint64_t base, int exp) {

  uint64_t result = 1;

  while (exp > 0) {

    if (exp % 2 == 1) { // 如果指数是奇数,先乘一次 base

      result = (result * base) % MOD;

    }

    base = (base * base) % MOD; // 底数平方,指数减半的准备

    exp /= 2; // 指数除以 2(整数除法,自动去掉余数)

  }

  return result;

}

 

 

- 干啥的:高效计算  base^exp % MOD 。比如算 3^{10},普通方法要乘 10 次,但快速幂通过 “指数二分”,只需要几次循环就能算完(像 3^{10} = (3^5)^2 = ((3^2)^2 \times 3)^2 这样拆)。

- 为啥用:计算大指数的幂时,直接硬算太慢,快速幂能大幅减少计算次数,还能结合  % MOD  避免数值太大。

 

(2) comb :算组合数 C(n, k)(即从  n  个里选  k  个的方案数)

 

int comb(int n, int k) {

  if (k > n) return 0; // 选的比总数还多,不可能,返回 0

  if (k == 0 || k == n) return 1; // 选 0 个或者全选,只有 1 种方案

 

  uint64_t numerator = 1; // 分子:n*(n-1)*...*(n-k+1)

  uint64_t denominator = 1; // 分母:k*(k-1)*...*1 

  for (int i = 0; i < k; ++i) {

    numerator = (numerator * (n - i)) % MOD;

    denominator = (denominator * (i + 1)) % MOD;

  }

  // 组合数公式:C(n,k) = 分子 / 分母 ,但这里用 “费马小定理” 转成乘法

  return (numerator * fast_pow(denominator, MOD - 2)) % MOD;

}

 

 

- 核心逻辑:组合数公式是 C(n,k) = \frac{n!}{k!(n - k)!} ,但直接算阶乘容易溢出,所以这里拆成 “分子乘、分母乘”,最后用 费马小定理 把除法转成 “乘以分母的模逆元”(因为  MOD  是质数,所以逆元是  denominator^(MOD-2) % MOD  )。

- 举个栗子:算 C(5,2) ,分子是 5 \times 4 = 20 ,分母是 2 \times 1 = 2 ,结果就是 20 / 2 = 10 ;代码里会用  fast_pow(2, MOD-2)  算出 2 的逆元,再用  20 * 逆元 % MOD  得到结果。

 

(3) countGoodArrays :最终计算符合条件的数组数目

 

int countGoodArrays(int n, int m, int k) {

  uint64_t res = m; 

  res = ((res * fast_pow(m - 1, n - k - 1)) % MOD) * comb(n - 1, k);

  return res % MOD;

}

 

 

- 思路对应题目分析:

- 题目里说 “每个位置选数,有 1~m 共 m 种选择”,但要恰好  k  对相邻相等。可以理解成:

- 第一个数随便选,有  m  种可能(对应代码里  res = m  )。

- 剩下的位置里,需要选  k  个位置让它和前一个数相等(这一步用  comb(n - 1, k)  算有多少种选法);剩下的  (n - 1 - k)  个位置 必须和前一个数不同,每个位置有  m - 1  种选法(所以用  fast_pow(m - 1, n - k - 1)  算这些位置的总方案数)。

- 把这些乘起来: m * (m-1)^(n - k - 1) * C(n-1, k)  ,就是最终符合条件的数组总数。

- 举个栗子:假设  n=3 , m=2 , k=1 (数组长度 3,数选 1/2,恰好 1 对相邻相等)

- 第一个数:2 种选法(比如选 1 或者 2)。

- 剩下  n-1=2  个位置里选  k=1  个位置让它和前一个相等 →  C(2,1)=2  种选法(比如位置 2 相等、位置 3 不等;或者位置 3 相等、位置 2 不等 )。

- 剩下  n - k - 1 = 3 - 1 - 1 = 1  个位置必须 “不等”,每个位置有  m-1=1  种选法 →  1^1=1  。

- 总数就是  2 * 1 * 2 = 4  ,可以手动验证是否符合预期~

 

4. 整体流程总结

 

1. 用  fast_pow  快速算幂取模,解决大指数计算问题。

2. 用  comb  算组合数,通过 “分子分母分别乘 + 费马小定理转逆元” 避免阶乘溢出。

3. 最后  countGoodArrays  把这些组合起来:先定第一个数的选法,再算 “选哪些位置相邻相等”,以及 “剩下位置不相等的选法”,三者相乘就是答案。

 

这样拆解下来,应该能明白每一步的作用啦~ 本质是把题目里的组合逻辑,用数学上的 “组合数” + “快速幂” 转化成代码,高效算出结果 。

RAII

RAII(Resource Acquisition Is Initialization,资源获取即初始化 )是 C++ 编程技术/范式

核心是将资源(堆内存、线程、套接字、文件、锁等有限资源 )的生命周期与对象生命周期绑定

借栈上局部变量自动析构,保证资源一定被释放

消除泄漏、确保异常安全,具体:
 
- 资源绑定:构造对象时获取资源(如构造函数里开文件、锁互斥量 )。
 
- 自动释放:对象生命周期结束(离开作用域等 ),析构函数自动释放资源(关文件、解锁 ),哪怕程序异常也会执行。
 
- 典型应用:智能指针( unique_ptr / shared_ptr  管内存 )、

锁管理( lock_guard  管锁 )、

文件流( ofstream / ifstream  管文件 ) ,

让资源管理更简洁、安全,少手动释放出错风险。

 

 

解码

class Solution {
public:
    string freqAlphabets(string s) 
    {
        int n = s.size();
        string ret;
        for(int i = 0; i < n; )
        {
            if(i + 2 < n && s[i+2] == '#')
            {

//预判断
                string ss = string(1, s[i]) + s[i+1];
                int tmp = stoi(ss);
                ret += 'a' + tmp - 1;
                i += 3;
            }
            else
            {
                int tmp = s[i] - '0';
                ret += 'a' + tmp - 1;
                i++;
            }
        }
        return ret;
    }
};
 

合作过的导演和演员

SELECT 

    actor_id,

    director_id

FROM 

    ActorDirector

GROUP BY 

    actor_id,director_id

-- 选出合作过的导演和演员

HAVING COUNT(*)>=3

-- 筛选出合作次数大于等于3的组合

 

相关文章:

  • 【AI News | 20250617】每日AI进展
  • JDBC强化关键_009_连接池
  • react 状态改变引发视图频繁更新,怎么优化
  • k均值聚类+成分分析降维+自编码器降维
  • Spring三层架构
  • VS和VS Code 对比和区别
  • Springboot整合ollama运行本地AI大模型
  • 利用Enigma Virtual Box将QT生成的软件打包成一个exe可执行文件
  • C++ map代码练习 1、2、priority_queue基础概念、对象创建、数据插入、获取堆顶、出队操作、大小操作,自定义结构、代码练习 1 2
  • Linux -- Ext系列文件系统介绍
  • 游戏引擎学习路径与技术栈指南
  • python+uniapp微信小程序的共享雨伞租赁系统
  • Day.34
  • JVM: 内存、类与垃圾
  • API 管理系统实践指南:监控、安全、性能全覆盖
  • MCP基本概念
  • synchronized 做了哪些优化?
  • 【Algorithm】图论入门
  • 软件体系结构-论述、设计、问答
  • 每天一个前端小知识 Day 4 - TypeScript 核心类型系统与实践
  • 国内好的网站建设/国内重大新闻10条
  • 成都网站搜索优化/杭州谷歌推广
  • wordpress发送到朋友圈美图/seo综合优化公司
  • 美容医疗手机网站模板/网络营销网站推广方法
  • 做网站手机版/seo排名工具
  • 微网站与普通网站的区别/建立网站的基本流程