#6556. 2026/4/24/ZYS课堂笔记
2026/4/24/ZYS课堂笔记
一、日期计算:累计天数函数
1. 问题描述
给定日期 (y, m, d),计算从 公元1年1月1日 到该日期的总天数(不含1年1月1日当天)。
2. 完整代码(修正语法错误版)
#include<bits/stdc++.h>
#define int long long
using namespace std;
// 判断闰年:能被4整除但不能被100整除,或能被400整除
bool is_leap(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 计算从1年1月1日到 (y,m,d) 的总天数
int js(int y, int m, int d) {
int ans = 0;
// 1. 累加完整年份的天数
for (int year = 1; year < y; year++) {
ans += is_leap(year) ? 366 : 365;
}
// 2. 累加当前年完整月份的天数
int days_in_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
if (is_leap(y)) days_in_month[2] = 29; // 闰年2月+1天
for (int month = 1; month < m; month++) {
ans += days_in_month[month];
}
// 3. 累加当前月的天数(不含当天)
ans += d - 1;
return ans;
}
signed main() {
// 示例:计算2026-04-24的总天数
cout << js(2026, 4, 24) << endl;
return 0;
}
3. 关键点解析
- 闰年判断:
(year%4==0 && year%100!=0) || (year%400==0) - 效率优化:原代码用
while循环逐年累加,可优化为数学公式(如365*(y-1) + (y-1)/4 - (y-1)/100 + (y-1)/400),避免循环。 - 语法修正:原代码中
yue == 3 5 7 8 10 12需改为yue == 3 || yue == 5 || ...(逻辑或连接)。
二、递推与取模:防止数据溢出
1. 问题背景
递推公式:f[i] = f[i-1] + 2*f[i-2],初始条件 f[0]=1, f[1]=1,求 f[n] % 1e9(因数据增长极快,需取模防止溢出)。
2. 代码片段与解析
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M = 1e9;
const int N = 1e5 + 10; // 假设n的范围
int f[N];
signed main() {
int n; cin >> n;
f[0] = 1;
f[1] = 1;
for (int i = 2; i <= n; i++) {
f[i] = (f[i-1] + 2 * f[i-2]) % M; // 每步取模,防止溢出
}
cout << f[n] << endl;
return 0;
}
3. 取模运算核心性质
(a + b) % mod = [(a % mod) + (b % mod)] % mod(a * b) % mod = [(a % mod) * (b % mod)] % mod- 意义:每步取模可将数据控制在
mod范围内,避免long long溢出。
三、贪心算法:出租车最少费用计算
1. 题目规则
- 前4km:10元(2.5元/km)
- 4~8km:2元/km(性价比最高)
- 超过8km:2.4元/km
- 目标:给定路程
n,求最少费用。
2. 完整代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
// 计算路程lc的最少费用
double js(int lc) {
if (lc == 0) return 0;
if (lc <= 4) return 10;
if (lc <= 8) return 10 + 2 * (lc - 4);
int full_8 = lc / 8; // 完整8km的段数
int remain = lc % 8; // 剩余路程
double ans = full_8 * 18; // 每8km费用18元(10+2*4)
// 贪心策略:剩余路程<=4km时,按2.4元/km补;否则单独跑一段
if (remain <= 4) ans += 2.4 * remain;
else ans += 10 + 2 * (remain - 4);
return ans;
}
signed main() {
int n;
while (cin >> n && n != 0) {
double ans = js(n);
if (ans == (int)ans) cout << (int)ans << endl;
else printf("%.1lf\n", ans);
}
return 0;
}
3. 贪心策略解析
- 性价比分析:前8km平均费用
18/8 = 2.25元/km(最优),因此优先按8km分段。 - 余数处理:
- 剩余
<=4km:按2.4元/km补(比单独跑一段更便宜); - 剩余
>4km:单独跑一段(10元起步+2元/km)。
- 剩余
四、基础语法:数组与sort函数
1. 卡牌交换问题思路
- 若两副卡牌的数字频率完全相同,可通过“交换位置”变得一模一样;
- 本质:用数组统计每个数字的出现次数,比较频率数组是否一致。
2. sort函数用法演示
#include<bits/stdc++.h>
using namespace std;
int main() {
int a[10] = {5, 2, 8, 1, 9};
// sort(起始地址, 结束地址+1)
sort(a, a + 5); // 对前5个元素排序(下标0~4)
for (int i = 0; i < 5; i++) cout << a[i] << " "; // 输出:1 2 5 8 9
cout << endl;
// 数组名的含义:数组首地址
cout << "数组首地址:" << a << endl;
cout << "第二个元素地址:" << a + 1 << endl;
return 0;
}
3. 关键点
- sort参数:左闭右开区间
[start, end),因此结束地址需+1;