2022 Hangzhou A.Modulo Ruins the Legend
A. Modulo Ruins the Legend$$求 \quad (\sum\limits_{i = 1}^{n} a_{i} + ns + \frac{n(n + 1)}{2}d) \quad % \quad m \quad 最小$$
$$由裴蜀定理知 \quad ax + by = k \times gcd(a, b)$$
$$令 \quad sum = \sum\limits_{i = 1}^{n} a_{i} \quad \Rightarrow \quad 原式 = sum + k \times gcd(a, b)$$
$$(sum + k \times gcd(a, b)) \quad % \quad m \quad = \quad (sum + k \times gcd(a, b) + pm) \quad % \quad m$$
$$再一次裴蜀定理 \quad k \times gcd(a, b) + pm = t \times gcd(a, b, m)$$
$$即 \quad (sum + t ...
Functional Language Features Iterators and Closures
Functional Language Features Iterators and ClosuresClosures: Anonymous Functions that Capture Their Environment闭包:可以捕获其所在环境的匿名函数
闭包的定义
123|parameters: type, ...| -> type { code}
参数和返回值的类型可以不用显示标注,编译器会自动推断
可以将闭包赋值给变量调用
123let f = |num: i32| { num};
如何让 struct 持有闭包
需要泛型和 Fn Trait
123456789101112131415161718192021222324252627282930struct Cacher<T> where T: Fn(i32) -> i32,// 参数和返回值{ cal: T, value: Option<i32>,}impl<T> Cacher& ...
An IO Project Building a Command Line Program
An IO Project Building a Command Line ProgramAccepting Command Line Arguments使用 std::env::args() 获得命令行参数迭代器
1234567891011use std::env;fn main() { let args: Vec<String> = env::args().collect(); println!("{:#?}", args);}// output[ "target\\debug\\rust.exe",]
添加自定义参数
cargo build
cargo run -- command line
例如
12345678cargo buildcargo run -- 2024 scut// output[ "target\\debug\\rust.exe", "2024", "scut",] ...
Writing Automated Tests
Writing Automated TestsHow to Write Testscargo test 会执行所有测试,即 #[test] 下的测试
1234567#[cfg(test)]mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); }}
输出信息
1234running 1 testtest tests::it_works ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
测试 panic 表示失败
assert! 宏, 当为假时,会 panic
12assert!(true);assert!(0 == 1);// false
assert_eq! 与 assert_ne! 即断言相等与不相等
断言失败会打印参数的值,要求实现了 PartialEq 和 Debug Traits (基本类 ...
Generic Types, Traits, and Lifetimes
Generic Types, Traits, and LifetimesRemoving Duplication by Extracting a Function如果代码需要重复使用,考虑封装成函数
Generic Data Types泛型:提高代码的复用性
函数泛型格式
123fn fn_name<T,...>(paraments...) -> type { }
可以看到只需要加<T..> 即可
123456789101112fn max_element<T>(item: &[T]) -> T { let mut val = item[0]; for &x in item { if x > val { val = x; } } return val;}// binary operation `>` cannot be applied to type ...
Error Handling
Error HandlingUnrecoverable Errors with panic!Rust 的 可靠性:错误处理,大部分情况下:在编译时提示错误并处理
错误分类:
可恢复:例如文件未找到,可再次尝试
不可恢复:例如访问索引超出范围
默认情况下,当 panic 发生:
程序展开调用栈 (工作量大)
Rust 沿着调用栈回走
清理每个遇到的函数中的数据
或 立即终止调用栈
不清理内存,直接停止程序,内存需要 OS 进行清理
panic! 宏
产生 panic 打印路径,行等信息
123panic!("crash");// thread 'main' panicked at src\main.rs:3:5:crash
panic!可能出现在我们写的代码中,我们所依赖的代码中
通过设置环境变量 RUST_BACKTRACE 可以得到回溯信息
Recoverable Errors with ResultResult 枚举
1234pub enum Result<T, E> { Ok(T), Err(E) ...
Common Collections
Common CollectionsVector创建Vector123456let x: Vec<i32> = Vec::new();// 创建Vector// Vector<T> 中类型一样// 可以显示声明 T 类型, 也可以编译器推断出 type// 使用宏 vec! 来创建初始Vec<T>let x = vec![1, 2, 3];
添加元素1234567// 添加元素let mut v = Vec::new();v.push(1);v.push(2);for x in v.iter() { println!("{}", x);}
删除Vector 当 Vector 离开作用域时会被删除
访问 Vector 中的元素1.索引 data_name[index]
2.get data_name.get(index)
12345678let x = vec![1, 2, 3, 4];println!("{}", x[3]);// ...
Managing Growing Projects with Packages, Crates, and Modules
Managing Growing Projects with Packages, Crates, and ModulesPackages and CratesPackagePackage(包) : Cargo 的特性,让你构建、测试、共享 crate
Crate(单元包) : 模块树,它可产生一个 library 或可执行文件
Module(模块), use : 让你控制代码的组织、作用域、私有路径
Path(路径) : 为 struct、function 或 module 等项命名的方式
Cargo 的惯例
12345678src/main.rs: - binary crate 的 crate root - crate 名与 package 名相同src/lib.rs: - package 包含一个 library crate - library crate 的 crate root - crate 名与 package 名相同
12345678一个 package 可以同时包含 src/main.rs 和 src/lib.rs - 名称与 package 名相 ...
Using Structs to Structure Related Data
Using Structs to Structure Related DataDefining and Instantiating Structs格式
1234struct Data_name { data1: type1, data2: type2,}// 注意无;
123456struct Data { name: String, age: u32, gender: bool, balance: f32,}
初始化一个 struct 对象
123456let user = Data { name: String::from("SCUT"), age: 1900, gender: true, balance: 0.0,};
访问对象中的元素
1println!("{} {} {} {}", user.name, user.age, use ...
Understanding Ownership
Understanding OwnershipWhat Is Ownership?所有权是 rust 用来管理内存的,本节内容很重要,毕竟 rust 主打内存安全
内存一般为 stack 和 heap
在编译时可以确定大小的一般放在 stack
例如 String(可变) 内容放在 heap, 但是 size, capacity 等信息占用的内存是固定的,会放在 stack
特性
123// 超出作用域 内存回收let t = s;// String 编译时大小不确定 复制为浅拷贝 move # heap 内存未复制println!("{}", s); //Error! value borrowed here after move #
当我们复制时只有 stack 部分复制,heap 内容未复制,此时所有权交给了 t ,此时用 s 会引发错误
123let x = 0;let y = x;println!("{} {}", x, y);// right
普通类型大小确定,在 stac ...