一、求1+2+3+...+n
class Sum
{
public:
Sum()
{
_ret += _i;
++_i;
}
static int GetRet()
{
return _ret;
}
private:
static int _i;
static int _ret;
};
int Sum::_i = 1;
int Sum::_ret = 0;
//C++规定对象实例化必须调用构造
class Solution {
public:
//成员函数
int Sum_Solution(int n) {
// 变⻓数组
Sum arr[n];
return Sum::GetRet();
}
};这段代码由 3 个核心部分 组成,分工明确:
// 1. 辅助累加类:负责实现「每次创建对象就累加一个数」的逻辑
class Sum { ... };
// 2. 静态成员初始化:静态变量必须在类外初始化(不属于任何对象)
int Sum::_i = 1;
int Sum::_ret = 0;
// 3. 求解类:提供对外的求和接口,控制累加的次数(即 1~n 的范围)
class Solution {
public:
int Sum_Solution(int n) { ... } // 求和核心接口
};Sum—— 真正实现 “累加” 的工具Sum 类的作用是「通过构造函数自动累加」,每个成员都有明确分工
class Sum
{
public:
// (1)构造函数:名字和类名相同,无返回值,创建对象时自动调用
Sum()
{
_ret += _i; // 核心操作1:把当前要加的数(_i)累加到总和(_ret)
++_i; // 核心操作2:让下一个要加的数自增1(比如这次加1,下次加2)
}
// (2)静态成员函数:获取累加结果的“接口”
static int GetRet()
{
return _ret; // 返回已经累加好的总和
}
private:
// (3)静态成员变量:所有对象共享,生命周期和程序一致(存在静态区)
static int _i; // 记录「当前要累加的数字」,初始值1(从1开始加)
static int _ret; // 记录「累加的总和」,初始值0(一开始总和为0)
};关键说明(为什么用「静态成员」?)
_i 和 _ret 是普通成员变量:每个 Sum 对象会有独立的 _i 和 _ret 副本(比如对象 1 的 _i=1,对象 2 的 _i 也是 1),无法实现 “1→2→3→…→n” 的连续累加;static 静态成员:所有 Sum 对象共享同一个 _i 和 _ret(比如对象 1 改了 _i=2,对象 2 用的就是 2),才能实现 “累加传递”。int Sum::_i = 1; // 初始化「当前要累加的数」为1(从1开始求和)
int Sum::_ret = 0; // 初始化「累加总和」为0(初始无任何累加)Solution—— 控制求和范围的 “总指挥”class Solution {
public:
int Sum_Solution(int n) { // n是求和上限(比如n=5就是求1+2+3+4+5)
Sum arr[n]; // 核心操作:创建一个长度为n的Sum类型数组(变长数组)
return Sum::GetRet(); // 返回累加好的总和
}
};关键说明(
Sum arr[n]到底做了什么?)
Sum 对象,创建数组时会依次创建这 n 个对象;Sum 对象,就会自动调用一次 Sum 类的构造函数(也就是执行 _ret += _i; ++_i;);n=3 为例,求 1+2+3)我们模拟调用 Solution().Sum_Solution(3) 后的每一步,看代码如何一步步算出结果:
Sum_Solution(3)n=3,表示要计算 1+2+3;Sum arr[3]:创建长度为 3 的数组,需要依次创建 3 个 Sum 对象(arr [0]、arr [1]、arr [2])。arr[0]—— 触发第一次构造函数_ret += _i → _ret = 0 + 1 = 1(总和现在是 1);++_i → _i = 1 + 1 = 2(下一个要加的数是 2);_ret=1,_i=2。arr[1]—— 触发第二次构造函数_ret += _i → _ret = 1 + 2 = 3(总和现在是 3);++_i → _i = 2 + 1 = 3(下一个要加的数是 3);_ret=3,_i=3。arr[2]—— 触发第三次构造函数_ret += _i → _ret = 3 + 3 = 6(总和现在是 6);++_i → _i = 3 + 1 = 4(下一个要加的数是 4,但已经用不到了);_ret=6,_i=4。Sum::GetRet(),获取静态成员 _ret 的值(6);Sum_Solution(3) 函数返回 6,即 1+2+3 的结果。class Solution {
// 内部类
class Sum {
public:
Sum() {
_ret += _i;
++_i;
}
};
static int _i;
static int _ret;
public:
int Sum_Solution(int n) {
// 变⻓数组
Sum arr[n];
return _ret;
}
};
int Solution::_i = 1;
int Solution::_ret = 0;#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
,_month(month)
,_day(day)
{ }
// 得到当月天数(处理闰年二月)
int GetMonthDay(int year, int month)
{
assert(month > 0 && month < 13);
// 月份天数数组(下标0不用,下标1对应1月)
static int monthDayArray[13] = { -1, 31,28,31,30,31,30,31,31,30,31,30,31 };
// 闰年二月特殊处理
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
return 29;
}
else
{
return monthDayArray[month];
}
}
//检查日期是否合法
bool CheckDate()
{
if (_month < 1 || _month>12)
return false;
if (_day<1 || _day>GetMonthDay(_year, _month))
return false;
return true;
}
// 根据“年+第n天”计算对应的月和日
void SetDateByDay(int year, int n)
{
_year = year;
_month = 1;
// 循环减去每个月的天数,直到n小于当月天数
while (n > GetMonthDay(_year, _month))
{
n = n - GetMonthDay(_year, _month);
_month++;
}
_day = n;
}
// 格式化输出日期(yyyy-mm-dd)
void Print()
{
// 输出年份(直接输出,年份是4位不用补0)
cout << _year << "-";
// 月份:小于10则补0,否则直接输出
if (_month < 10)
{
cout << "0" << _month;
}
else
{
cout << _month;
}
cout << "-";
// 日期:小于10则补0,否则直接输出
if (_day < 10)
{
cout << "0" << _day;
}
else
{
cout << _day;
}
// 换行
cout << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int year, n;
// 多组输入:年 + 第n天
while (cin >> year >> n) {
Date d;
d.SetDateByDay(year, n); // 计算对应日期
d.Print(); // 格式化输出
}
return 0;
}//累加天数
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{ }
//得到每个月的天数
int GetMonthDay(int year, int month)
{
assert(month >= 1 && month <= 12);
int arr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
return 29;
}
else
{
return arr[month];
}
}
//检查日期是否合法
bool CheckDate()
{
if (_month >= 13 || _month < 1)
{
return false;
}
if (_day < 1 || _day > GetMonthDay(_year, _month))
{
return false;
}
return true;
}
// 日期累加days天
void AddDays(int days)
{
_day += days;
while (true)
{
if (_day <= GetMonthDay(_year, _month))
{
break; // 天数在当月范围内,结束
}
// 天数超过当月,减去当月天数,月份+1
_day -= GetMonthDay(_year, _month);
_month++;
if (_month > 12) { // 月份超过12,年份+1,月份重置为1
_year++;
_month = 1;
}
}
}
//格式化输出
void Print()
{
cout << _year << "-";
if (_month < 10)
{
cout << "0" << _month;
}
else
{
cout << _month;
}
cout << "-";
if (_day < 10)
{
cout << "0" << _day;
}
else
{
cout << _day;
}
cout << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int m;
cin >> m;
while (m--)
{
int year, month, day, AddDay;
cin >> year >> month >> day >> AddDay;
Date d(year, month, day);
d.AddDays(AddDay);
d.Print();
}
return 0;
}#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{ }
//得到每个月的天数
int GetMonthDay(int year, int month)
{
assert(month >= 1 && month <= 12);
int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
return 29;
}
else
{
return arr[month];
}
}
//判断日期是否在正确区间
bool CheckDate()
{
if (_month > 12 || _month < 1)
return false;
if (_day<1 || _day>GetMonthDay(_year, _month))
return false;
return true;
}
//日期加法
int add(int sum)
{
sum = _day; // 先算当月的天数(核心:先加_day,再累加之前的月份)
_month--; // 从上个月开始累加(因为当月的day已经算过了)
while (_month > 0) // 只要月份还大于0,就继续累加
{
sum += GetMonthDay(_year, _month); // 累加前一个月的天数
_month--; // 月份继续减,直到1月
}
return sum; // 最终返回的就是“当年第几天
}
void Print()
{
cout << add(0) << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
int year, month, day;
while (cin >> year >> month >> day)
{
//别忘记传值,不然会调用默认构造
Date d(year, month, day);
d.Print();
}
return 0;
}当然这里的add是有优化空间的,我们可以创建一个临时变量就可以保留下_month的值,方便后续的二次使用(本题没有二次使用,所以使用哪个都可以):
//日期加法
int add(int sum)
{
int tmp_month = _month;
sum = _day;
tmp_month--;
while (tmp_month > 0)
{
sum += GetMonthDay(_year, tmp_month);
tmp_month--;
}
return sum;
}这题还可以使用枚举是个非常暴力破解的方法:
#include<iostream>
using namespace std;
int main()
{
int year, month, day;
while (cin >> year >> month >> day)
{
int monthDays[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
int nday = monthDays[month - 1] + day;
if (month > 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
{
nday += 1;
}
cout << nday << endl;
}
return 0;
}#define _CRT_SECURE_NO_WARNINGS 1
//有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天
//有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD
//每组数据输出一行,即日期差值
#include<iostream>
#include<assert.h>
#include<string>
#include<cmath> // 用于abs()取绝对值
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{
}
// 判断是否为闰年
bool isLeap() const {
return ((_year % 4 == 0 && _year % 100 != 0) || (_year % 400 == 0));
}
// 获取当月天数
int getMonthDays() const {
int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (_month == 2 && isLeap()) {
return 29;
}
return days[_month];
}
// 计算当前日期距离基准年(1年)的总天数
long long getTotalDays() const {
long long total = 0;
// 累加之前所有年份的天数
for (int y = 1; y < _year; ++y) {
total += ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) ? 366 : 365;
}
// 累加当年的天数
for (int m = 1; m < _month; ++m) {
int d[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (m == 2 && isLeap()) {
total += 29;
}
else {
total += d[m];
}
}
total += _day;
return total;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
string dateStr1;
string dateStr2;
while (cin >> dateStr1 >> dateStr2) // 读取每一行的日期字符串(比如"20110412")
{
//这里是连续输入字符串我们需要调用string类中的substr来辅助我们实现
//string的substr是C++中用于截取字符串子串的成员函数,作用是从原字符串中提取一部分内容,返回一个新的字符串
// 拆分年、月、日:前4位→年,中间2位→月,最后2位→日
int year1 = stoi(dateStr1.substr(0, 4)); // 从索引0开始取4个字符→年
int month1 = stoi(dateStr1.substr(4, 2)); // 从索引4开始取2个字符→月
int day1 = stoi(dateStr1.substr(6, 2)); // 从索引6开始取2个字符→日
int year2 = stoi(dateStr2.substr(0, 4)); // 从索引0开始取4个字符→年
int month2 = stoi(dateStr2.substr(4, 2)); // 从索引4开始取2个字符→月
int day2 = stoi(dateStr2.substr(6, 2)); // 从索引6开始取2个字符→日
//stoi是C++11引入的标准库函数
//全称是string to integer核心作用是把字符串类型的数字(如 "2011"、"04")转换成整数类型(int)
//是处理字符串数字拆分(比如日期拆分)的核心函数
Date d1(year1, month1, day1);
Date d2(year2, month2, day2);
// 计算差值(题目规则:连续日期计为2天,即差值+1)
long long diff = abs(d1.getTotalDays() - d2.getTotalDays()) + 1;
cout << diff << endl;
}
return 0;
}#include <iostream>
using namespace std;
//思路:1.分别求出每一个日期与0000年0月1日距离的天数
// 2.两个距离天数相减即可得到两个日期相差的天数
//平年从1月到n月的天数
int mon[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
//给出年月日,计算距离0000年0月1日的天数和
int CountDay(int y, int m, int d)
{
// 计算0-y年的天数
int yearDay = y * 365 + y / 4 - y / 100 + y / 400;
// 计算到0-m月的天数
int monthDay = mon[m - 1];
if (m > 2 && ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0))
monthDay += 1;
return yearDay + monthDay + d;
}
int main()
{
int year1, month1, day1;
scanf("%4d%2d%2d", &year1, &month1, &day1);
int n1 = CountDay(year1, month1, day1);
int year2, month2, day2;
scanf("%4d%2d%2d", &year2, &month2, &day2);
int n2 = CountDay(year2, month2, day2);
cout << abs(n1 - n2) + 1 << endl;
}核心优势