C++程序基础(18):C++循环综合例题(1)

C++循环综合例题(1)

例题:洛谷B3737双十一


题目描述:
每年 11 11 11 11 11 11 日,各大网上商店都会有促销活动,因此大家都希望 11 11 11 11 11 11 日在周末,就可以更愉快地购物啦。请你写一个程序计算一段时间中, 11 11 11 11 11 11 日是周末(周六或周日)的数量。以下关于日期的定义和事实能帮到你:

  1. 1900 1900 1900 1 1 1 1 1 1 日是星期一
  2. 每年的 1 , 3 , 5 , 7 , 8 , 10 , 12 1,3,5,7,8,10,12 1,3,5,7,8,10,12 月有 31 31 31 天; 4 , 6 , 9 , 11 4,6,9,11 4,6,9,11 月有 30 30 30 天;闰年的 2 2 2 月有 29 29 29 天,非闰年的 2 2 2 月有 28 28 28 天。
  3. 闰年的计算方法:不能被 100 100 100 整除的年份称为普通年。普通年能被 4 4 4 整除的为闰年,因此 2004 2004 2004 年是闰年, 1999 1999 1999 年不是闰年;能被 100 100 100 年整除的年份称为世纪年。世纪年能被 400 400 400 整除的是闰年,因此 2000 2000 2000 年是闰年, 1900 1900 1900 年不是闰年。

输入格式:

输入一行两个整数 x , y x,y x,y ,代表需要计算的起止年份。


输出格式:

输出一个整数,第 x x x 年到第 y y y 年中 11 11 11 11 11 11 日是周末的年数(包括第 x x x 年和第 y y y 年)


输入样例:

2018 2100

输出样例:

23

数据范围:
1900 < = x < = y < = 3000 1900<=x<=y<=3000 1900<=x<=y<=3000


分析


本题的题意是要求输出在第 x x x 年和第 y y y 年范围内的 11 11 11 11 11 11 日是周末的数量

那么有人可能会说:只要把第一个 11 11 11 11 11 11 日是星期几算出来,后面的都可以推出来了?

但是,闰年的问题仍然无法避免

所以我们可以先用循环算出第一年的双十一是星期几,然后再判断下一年是否是闰年,将对应天数除以一个星期七天,算出下一年的双十一是星期几即可。

代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int x,y;
	cin>>x>>y;
	int day=1,mon=1,date=1;
	for(int i=2;i<=365;i++)
	{
		date++;
		day++;
		if(day==8)
		{
			day=1;
		}
		if((mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)&&date>31)//月份进位
		{
			date=1;
			mon++;
		}
		else if(mon==2&&date>28)
		{
			mon++;
			date=1;
		}
		else if(date>30&&(mon==4||mon==6||mon==9||mon==11))
		{
			mon++;
			date=1;
		}
		if(mon==11&&date==11)
		{
			break;
		}
	}//以上代码是找1900年11月11日是星期几,自己的代码可以直接写星期日,缩减代码长度
	int ans=0;
	if(x<=1900)
	{
		ans++;
	}
	for(int i=1901;i<=y;i++)
	{
		int sum=365;
		if(i%4==0&&i%100!=0 || i%400==0)//判断是否为闰年
		{
			sum=366;
		}
		day+=sum%7;//加上空余天数
		if(day>7)
		{
			day-=7;//减去可能的多余
		}
		if(i>=x&&(day==6||day==7))//判断
		{
			ans++;
		}
	} 
	cout<<ans;
	return 0;
}

当然,这种代码可能需要一定的调试才能顺利通过数据,甚至可能控制不当还会出现反例

那么为了保证代码准确性,在考试时,我们可以采取穷举的算法

遍历一遍从 1900 1900 1900 年到 y y y 年的所有日子,判断即可

穷举算法:

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int x,y;
	cin>>x>>y;
	int date=1,day=1,mon=1,year=1900;
	int ans=0;
	while(y>=year)
	{
		date++;
		day++;
		if(day==8)
		{
			day=1;
		}
		int sum=365;
		if(year%4==0&&year%100!=0 ||(year%400==0))
		{
			sum=366;
		}
		if((mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)&&date>31)//月份进位
		{
			date=1;
			mon++;
		}
		if(mon==2)
		{
			if(sum==365&&date>28)
			{
				date=1;
				mon++;
			}
			if(sum==366&&date>29)
			{
				date=1;
				mon++;
			}
		}
		if(date>30&&(mon==4||mon==6||mon==9||mon==11))
		{
			mon++;
			date=1;
		}
		if(mon==11&&date==11&&(day==6||day==7)&&year>=x)
		{
			ans++;
		}
		if(mon==13)
		{
			mon=1;
			year++;
		}
	}
	cout<<ans;
	return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值