日期计算是编程中常见的需求,特别是在处理日志、排期等业务场景时。题目要求实现一个函数,能够计算给定日期n天后的日期。我们先来看基础实现思路:
cpp复制#include <iostream>
using namespace std;
// 计算当月剩余天数
int leftmonth(int year, int month, int day) {
bool isLeap = (year%4==0 && year%100!=0) || (year%400==0);
int daysInMonth;
if(month == 2) {
daysInMonth = isLeap ? 29 : 28;
} else if(month == 4 || month == 6 || month == 9 || month == 11) {
daysInMonth = 30;
} else {
daysInMonth = 31;
}
return daysInMonth - day;
}
注意:判断闰年时,能被400整除的世纪年是闰年,能被4整除但不能被100整除的普通年是闰年。这是格里高利历法的基本规则。
主函数处理的核心逻辑是逐步消耗天数n,直到剩余天数可以在当前月内处理:
cpp复制int main() {
int year, month, day, n;
cin >> year >> month >> day >> n;
while(true) {
int remainingDays = leftmonth(year, month, day);
if(n <= remainingDays) break;
n -= remainingDays;
month++;
if(month > 12) {
month = 1;
year++;
}
day = 0; // 重置为下个月的第0天(实际会+1)
}
day += n;
cout << year << " " << month << " " << day;
}
这段代码的巧妙之处在于:
实际工程中还需要考虑以下边界情况:
cpp复制// 验证输入日期合法性
bool isValidDate(int y, int m, int d) {
if(m < 1 || m > 12) return false;
if(d < 1) return false;
int maxDay;
switch(m) {
case 2:
maxDay = ((y%4==0 && y%100!=0) || y%400==0) ? 29 : 28;
break;
case 4: case 6: case 9: case 11:
maxDay = 30;
break;
default:
maxDay = 31;
}
return d <= maxDay;
}
观察N=2时的输出:
code复制 Z
Y X
W
可以发现以下规律:
cpp复制void printLine(int leading, int inner, char& current) {
// 前导空格
cout << string(leading, ' ');
// 第一个字母
cout << current;
current = (current == 'A') ? 'Z' : current - 1;
// 双字母情况
if(inner >= 0) {
cout << string(inner, ' ') << current;
current = (current == 'A') ? 'Z' : current - 1;
}
cout << endl;
}
技巧:使用string(n, char)快速生成重复字符比循环更高效
cpp复制int main() {
int N;
while(cin >> N) {
char ch = 'Z';
// 上半部分
for(int i=1; i<=N; ++i) {
int leading = N - i;
int inner = (i == 1) ? -1 : (2*i-3);
printLine(leading, inner, ch);
}
// 下半部分
for(int i=N-1; i>=1; --i) {
int leading = N - i;
int inner = (i == 1) ? -1 : (2*i-3);
printLine(leading, inner, ch);
}
cout << endl;
}
return 0;
}
题目要求统计周长为n且边长各不相同的整数三角形个数。根据三角形不等式:
cpp复制int countTriangles(int n) {
int count = 0;
for(int a=1; a<n/3; ++a) {
for(int b=a+1; b<(n-a)/2; ++b) {
int c = n - a - b;
if(a + b > c) {
count++;
}
}
}
return count;
}
算法优化点:
对于n=90的测试用例:
测试结果验证:
cpp复制assert(countTriangles(15) == 3); // 4,5,6 | 2,6,7 | 3,5,7
assert(countTriangles(12) == 1); // 3,4,5
assert(countTriangles(90) == 283);
日期计算时:
图案生成时:
三角形计数时:
实际项目中,这些算法可以进一步封装为工具类:
cpp复制class DateUtil {
public:
static Date addDays(Date start, int days);
static bool isValid(Date date);
};
class PatternGenerator {
public:
static void printDiamond(int size, char startChar='Z');
};
class TriangleCounter {
public:
static int countDistinct(int perimeter);
};
日期计算错误:
图案不对齐:
三角形计数遗漏:
调试技巧:
cpp复制cout << "Processing: " << year << "-" << month << "-" << day
<< ", remaining days: " << n << endl;
cpp复制cout << "[" << leading << " lead, " << inner << " inner]";
cpp复制cout << "Valid: " << a << "," << b << "," << c << endl;
这些算法虽然看似简单,但包含了循环控制、条件判断、数学建模等编程基础要素,是很好的练习题。在实际开发中,类似逻辑常用于日历组件、文本图形生成和组合数学计算等场景。