首页 > 试题广场 >

不吉利的日期

[编程题]不吉利的日期
  • 热度指数:1372 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
在国外,每月的 13 号和每周的星期 5 都是不吉利的。特别是当 13 号那天恰好是星期 5时,更不吉利。
现在给你一个年份,请你从小到大依次输出当年所有13 号是星期 5 的月份。

输入描述:
输入包含多组数据,每组数据包含一个正整数year(2000≤year≤9999)。


输出描述:
对应每一组数据,输出所有符合条件的月份,月份之间用空格隔开。
如果当年不存在13号是星期五的月份,就输出一行Luck。
示例1

输入

2000<br/>2001<br/>2002

输出

10<br/>4 7<br/>9 12
推荐
我的做法和前面的不一样
先分析完所有的情况,所有的阳历年历只有如下14种:
(依次编号L[0]~L[6]、C[0]~C[6])
第一类:元旦为周一的平年,元旦为周二的平年,...,元旦为周日的平年
第二类:元旦为周一的闰年,元旦为周二的闰年,...,元旦为周日的闰年
两个要素:(1)平年or闰年? (2)元旦为周几?
这两个要素一旦确定,全年的历表就确定了。
例如:元旦为周日的闰年,13th与Friday相遇的月份就一定是Jan. Apr. Jul.

剩下的工作就是找出年份year与L[x]或C[x]之间的对应关系,也就是求函数 x = f ( year )。
这个算法的时间复杂度O(n),空间复杂度O(1)。
#include<stdio.h>
int isLeapYear(int n){
	int rtn=0;
	if(n%400==0 || (n%100!=0 && n%4==0))rtn=1;
	return rtn;
}
int main(){
	char*L[7]={"1 4 7\n","9 12\n","6\n","3 11\n","2 8\n","5\n","10\n"};
	char*C[7]={"1 10\n","4 7\n","9 12\n","6\n","2 3 11\n","8\n","5\n"};
	int n;
	while(scanf("%d",&n)!=EOF){
		int flag=isLeapYear(n);
		n=(6+(n-2000)+(n-1997)/4+(n-2001)/400-(n-2001)/100)%7;
		char*s;
		if(flag)s=L[n];
		else s=C[n];
		printf("%s",s);
	}
	return 0;
}

编辑于 2016-05-28 10:25:41 回复(10)

python只要三行代码搞定。还可以进一步缩写我就不装逼了

import datetime
while True:
    try:
        year = int(input())
        res = " ".join(map(str, filter(lambda c: str(datetime.datetime(year, c, 13).strftime("%w")) == "5", range(1, 13))))
        print(res if res else "Luck")
    except:
        break
编辑于 2017-10-11 06:56:58 回复(0)
计算 周几 使用  吉姆拉尔森 算法 
#include <iostream>
#include <algorithm>
using namespace  std;
int month31[] = { 1,3,5,7,8,10,12 };
int CalculateWeekDay(int y, int m, int d) {
    if (m == 1 || m == 2) m += 12, y--;
    int iWeek = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
    return iWeek;
}


int main()
{
    int year;
    while (cin >> year)
    {
        int cnt = 0;
        for (int i = 1; i < 13; i++)
        {
            if (CalculateWeekDay(year, i, 13) % 7 == 4)
            {
                cnt++;
                if(cnt == 1)
                    cout << i;
                else
                {
                    cout << " " << i;
                }
            }
        }
        if (!cnt)
        {
            cout << "Luck" << endl;
        }
        else
        {
            cout << endl;
        }
    }
}

当然,使用C 的time.h 也是很好用的,不用计算,爽。
而且好记
#include <iostream>
#include <time.h>
#include <vector>
#include <fstream>
using namespace std;
#ifndef debug
ifstream ifile("case.txt");
#define cin ifile
#endif


int main() {
    struct tm timeInfo;
    int year;
    int month;
    int day;
    time_t rawtime;
    time(&rawtime);
    timeInfo = *localtime(&rawtime);// raw 应该是时间基线,不是特别清楚。
    while (cin >> year){
        timeInfo.tm_year = year - 1900;
        vector<int> count;
        for (int i = 0; i < 12; i++){
            month = i;
            day = 13;
            timeInfo.tm_mon = i;
            timeInfo.tm_mday = 13;
            mktime(&timeInfo);
            if (timeInfo.tm_wday == 5) {// 如果日期等于5
                count.push_back(i+1);
            }
        }
        if (count.size() == 0) {
            cout << "Luck" << endl;
        }
        else {
            cout << count[0];
            for (int i = 1; i < count.size(); i++) {
                cout << " " << count[i];
            }
            cout << endl;
        }
    }
    system("pause");
}

编辑于 2018-09-05 09:05:59 回复(0)
#include<stdio.h>

int get_days(int year, int m, int d)
{
    int day=0;
    int i;
    for(i=1; i < m; i++)
    {
        if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)
            day += 31;
        else
        {
            if(i!=2)
                day+=30;
            else
            {
                day += 28;
                if((year%4==0&&year%100!=0)||(year%400==0))
                    day += 1;
            }
        }
    }
    return 365*(year-1) + ((year-1)/4 - (year-1)/100 + (year-1)/400) + day + d;
}


int main()
{
    int year;
    while(scanf("%d", &year)!=EOF)
    {
        int cnt=0;
        int i;
        for(i=1; i<=12; i++)
        {
            int t = get_days(year,i,13)%7;
            if(t==5){
                cnt++;
                if(cnt>1)
                    printf(" ");
                printf("%d",i);
            }
        }
        if(cnt==0)
            printf("Luck");
        printf("\n");
    }
    return 0;
}

发表于 2015-09-24 09:23:35 回复(0)
#include<bits/stdc++.h>
using namespace std;
//思路 以2000 年10 月13日(星期五)为起点。算 给定年份的每个月的13号与2000 10 13天数差值(最大10000*365不超过int范围)
//如果差值是7的倍数 则输出当月月份即可
int daylab[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,
                  0,31,29,31,30,31,30,31,31,30,31,30,31};
bool IsLeap(int n){
    if((n%4==0&&n%100!=0)||(n%400==0)) return true;
    else return false;
}
int main(){
    int n;
    while(cin>>n){
        int sum=79;//2000年还剩79天
        if(n==2000) cout<<"10"<<endl;
        else{
            for(int i=2001;i<n;i++){//计算到前一年的天数差值
                if(IsLeap(i)==true){
                    sum+=366;
                }else{
                    sum+=365;
                }
            }
            //加上给定年份当年的差值
            for(int i=1;i<=12;i++){
                sum+=13;
                if(sum%7==0) cout<<i<<' ';
                sum-=13;
                sum+=daylab[IsLeap(n)][i];
            }
            cout<<endl;
        }
    }
    return 0;
}

发表于 2020-04-03 13:54:36 回复(0)
#include<stdio.h>
char* s[][7]={{"1 10","4 7","9 12","6","2 3 11","8","5"},{"1 4 7","9 12","6","3 11","2 8","5","10"}};
int main(int y){//the shorter,the better.
    for(;~scanf("%d",&y);printf("%s\n",s[y%400==0||(y%100!=0&&y%4==0)][(6+(y-2000)+(y-1997)/4+(y-2001)/400-(y-2001)/100)%7]));
}

发表于 2018-01-28 14:49:38 回复(0)
#include <iostream>
using namespace std;

void get_num_unlucky(int year)
{
	
	int day = (year - 1) * 365 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400; //前一年一共有多少天
	int type[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
	int kind = 1;
	if (year % 4 != 0 || year % 100 == 0 && year % 400 != 0) kind = 0;
	
	day += 13;
	for (size_t i = 0; i < 12; i++)
	{
		if (day % 7 == 5) cout << i + 1 << " ";
		day += type[kind][i];
	}
	cout << endl;
}

int main()
{
	int year;
	while (cin >> year)
	{
		get_num_unlucky(year);
	}
    return 0;
}

发表于 2020-07-27 21:58:58 回复(0)


这道题并不复杂,但是在细节控制方面有点繁琐。

我们要解决的问题是计算当年每个月的13号是星期几,年份输入的范围是2000≤year≤9999,直接求解可能比较难,我们一步一步逼近。

首先我们需要计算出输入年份的1月1日是星期几week,我们查找网络知2000年1月1日星期六

平年一年365天(52周+1天),闰年一年366天(52周+2天)。
也就是说平年一年过去后week = (week + 1) % 7,闰年一年过去后week = (week + 2) % 7,实际效果是闰年 = 平年 + 1

因此我们需要计算[2000, yea)中有多少个闰年
[2000, yea)期间总共有year - 2000年,闰年数量为(year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400

==注意:== 我们这里把2000年单独拿出来,因为当year == 2000时,2000年的闰年并不会影响2000年1月1号的计算。

因此==year年1月1日星期几week求解计算==过程为

int week = 6;//2000年1月1日 星期六,注意星期日用0表示
//计算该年1月1日星期几,平年365天(52周+1天)闰年366(52周+2天),也就是平年增加一天,闰年增加两天
//期间year - 2000年,(year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400 个闰年
week = (week + (year - 2000) + (year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400) % 7;
if (year > 2000) {
    //2000年也是l闰年,但是单独算,因为当year == 2000时,此时它虽是闰年,但是不影响2000年1月1日是星期几的计算
    week += 1;
}

知道了year年1月1日是星期几,记为week0,那么

year年1月12日 week1 = (week0 + 12) % 7
year年2月12日 week2 = (week0 + 31 + 12) % 7  注:1月31天
year年3月12日 week3 = (week0 + 31 + 28 or 29 + 12) % 7  注:平年 2月 28天,闰年 2月 29天
year年4月12日 week4 = (week0 + 31 + 28 or 29 + 31 + 12) % 7  注:3月 31天
...

#include <iostream>
using namespace std;

int main() {
    int resTable[12] = {0}, year = 0;
    //resTable存放当年13号为星期5的月份,monthDays[month]记录month月的天数,其中2月根据year是否为闰年动态调整
    int monthDays[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    //scanf函数范围值为正确获取到数据的参数个数,当没有输入返回-1
    while (scanf("%d", &year) != -1){
        //2000年1月1日 星期六,注意星期日用0表示,count记录13 号是星期 5 的月份个数
        int week = 6, count = 0;
        //计算该年1月1日星期几,平年365天(52周+1天)闰年366(52周+2天),也就是平年增加一天,闰年增加两天
        //期间year - 2000年,(year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400 个闰年
        week = (week + (year - 2000) + (year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400) % 7;
        if (year > 2000) {
            //2000年也是l闰年,但是单独算,因为当year == 2000时,此时它虽是闰年,但是不影响2000年1月1日是星期几的计算
            week += 1;
        }
        //如果当年是闰年,则二月有29天
        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
            monthDays[2] = 29;
        } else {
            monthDays[2] = 28;
        }
        //判断当年的每个月13号是不是星期5
        for (int month = 1; month < 13; ++month) {
            if ((week + 12) % 7 == 5) {
                //如果是就记录掉resTable中,count记录13 号是星期 5 的月份个数
                resTable[count++] = month;
            }
            //转到下个月的1号
            week += monthDays[month];
        }
        for (int i = 0; i < count - 1; ++i) {
            printf("%d ", resTable[i]);
        }
        printf("%d\n", resTable[count - 1]);
    }
    return 0;
}
————————————————
版权声明:本文为CSDN博主「hestyle」的原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://hestyle.blog.csdn.net/article/details/104717957
发表于 2020-03-07 17:16:06 回复(0)
#include <stdio.h>
#include <stdlib.h>

int leap[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int comm[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int is_leap(int year)
{
    if(year % 100 == 0)
    {
        if(year % 400 == 0)
            return 1;
        return 0;
    }
    if(year % 4 == 0)
        return 1;
    return 0;
}

int main()
{
    int year;
    while(~scanf("%d", &year))
    {
        int start = 2000;
        int total_day = 92;
        if(year == start)
        {
            printf("10\n");
            continue;
        }
        while((start + 1) != year)
        {
            if(is_leap(start+1))
                total_day += 366;
            else
                total_day += 365;
            start++;
        }
        start++;
        int temp = 0;
        for(int i = 1; i <= 12; i++)
        {
            if(is_leap(start))
            {
                if(total_day % 7 == 0)
                {
                    if(temp == 0)
                        printf("%d", i);
                    else
                        printf(" %d", i);
                    temp = 1;
                }
                total_day += leap[i];
            }
            else
            {
                if(total_day % 7 == 0)
                {
                    if(temp == 0)
                        printf("%d", i);
                    else
                        printf(" %d", i);
                    temp = 1;
                }
                total_day += comm[i];
            }
        }
        if(temp == 0)
            printf("Luck");
        printf("\n");
    }
    return 0;
}
以2000.10.13为起始点就行了
编辑于 2020-03-04 13:46:48 回复(2)

  1. 使用基姆拉尔森计算公式
  2. Week=(Day + 2*Month + 3*(Month+1)/5 + Year + Year/4 - Year/100 + Year/400) % 7
    #include <cstdio>
    
    int main(int argc, char const *argv[]){
        int year;
        while(scanf("%d", &year) != EOF){
            int cnt = 0;
            for (int month = 1; month <= 12; ++month) {
                int y = year;
                int d = 13;
                int m = month;
                if(m==1||m==2){
                    y = year - 1;
                    m+=12;
                }
                int w =(d+1+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;
                if(w == 5){
                    if(cnt != 0) printf(" ");
                    if(m > 12){
                        printf("%d", m -12);
                    }else{
                        printf("%d", m);                    
                    }
                    cnt++;
                }
            }
            if(cnt == 0){
                printf("Luck");
            }
            printf("\n");
        }
    
        return 0;
    }

发表于 2020-03-01 17:14:46 回复(0)
#include<iostream>
using namespace std;
bool isLeapYear(int year) {
    if((year%4==0&&year%100!=0)||year%400==0) {
        return true;
    }
    return false;
}
int main() {
    int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int year;
    long long days;
    while(cin>>year) {
        days=4;
        for(int i=2000;i<year;i++) {
            days+=365;
            if(isLeapYear(i)) {
                days++;
            }
        }
        for(int i=0;i<12;i++) {
            days+=month[i];
            if((days+13)%7+1==5) {
                cout<<i+1<<" ";
            }
            if(i==1&&isLeapYear(year)) {
                days++;
            }
        }
        cout<<endl;
    }
    return 0;
}
发表于 2019-08-04 13:41:56 回复(0)
import calendar
while True: 
    try:
        n=int(input())
        a=[] 
        for i in range(1,13):
            if calendar.monthrange(n,i)[0]==6:
                a.append(str(i)) 
        if a: 
            print(" ".join(a))  
        else:  
            print("Luck")  
    except:  
        break
编辑于 2019-06-22 10:46:33 回复(0)
dict = {2000: "10", 2001: "4 7", 2002: "9 12"}
week=1
for i in range(2003,10000):
    s = ""
    for j in range(1,13):
        if week==5:
            s+=(str(j)+" ")
        if j in (1,3,5,7,8,10,12):
            week=(3+week)%7
        elif j in (4,6,9,11):
            week=(2+week)%7
        if (i%400==0 or (i%100!=0 and i%4==0)) and j==2:
            week=(1+week)%7
    if s!="":
        dict[i]=s

while True:
    try:
        year = int(input())
        if year in dict:
            print(dict[year])
        else:
            print("Luck")
    except:
        break
发表于 2019-06-20 11:44:32 回复(0)
def day(a,b,nian,yue):
    con = (a+a//4+a//400-a//100-nian+yue+13)%7
    if con==5:
        return True
    else:
        return False
def ifrun(a):
    if a%400==0:
        return True
    elif a%100==0:
        return False
    elif a%4==0:
        return True
    else:
        return False
pinlst = [0,3,3,6,1,4,6,2,5,0,3,5]
runlst = [0,3,4,0,2,5,0,3,6,1,4,6]
try:
    while True:
        n = input()
        n = int(n)
        zong = 0
        out = []
        if ifrun(n):
            for i in range(1,13):
                if day(n,i,2,runlst[i-1]):
                    out.append(str(i))
        else:
            for i in range(1,13):
                if day(n,i,1,pinlst[i-1]):
                    out.append(str(i))
        print(" ".join(out))
except:
    pass
通过蔡勒公式进行计算
发表于 2018-12-02 09:36:52 回复(0)
请问题主,这种题型最主要察什么知识点?
发表于 2018-03-23 17:17:03 回复(0)
//大神们写得都过于牛逼,看不懂,还是自己动手
#include<stdio.h>
int isLeapYear(int n);
int main()
{
    int i, y;
    while(scanf("%d", &y)!=EOF)
    {
        int days = 4; //根据示例可以推算出2000年的1月13日是星期四
        int count = 0;
        for(i=2000; i<y; i++)
        {
            if(isLeapYear(i)==1)
            {
                days += 366;
            }
            else
            {
                days += 365;
            }
            days %= 7;
        }
        for(i=1; i<13; i++)
        {
            if(days==5)
            {
                if(count)
                {
                    printf(" ");
                }
                printf("%d", i);
                count++;
            }
            if(i==1||i==3||i==5||i==7||i==8||i==10)
            {
                days += 31;
            }
            else if(i==2)
            {
                if(isLeapYear(y)==1)
                {
                    days += 29;
                }
                else
                {
                    days += 28;
                }
            }
            else
            {
                days += 30;
            }  days %= 7;
        }
        printf("\n");
    }
    return 0;
}
int isLeapYear(int n)
{
    int rtn=0;
    if(n%400==0 || (n%100!=0 && n%4==0))
    {
        rtn=1;
    }
    return rtn;
}

编辑于 2017-12-07 21:46:27 回复(1)
#include<stdio.h>
int num[13]={0,31,-1,31,30,31,30,31,31,30,31,30,31};
int temp[13]={0,12,1,2,3,4,5,6,7,8,9,10,11};
int a[8000][12];
int RunYear(int n)
{
	if((n%4==0&&n%100!=0) || n%400==0)//闰年2月29天
		return 29;
	else
		return 28;
}
int main()
{
	//2000≤year≤9999
	int i,j,n,year,cnt=0,week=3;//week代表2000年12月13日是星期三
	a[0][0]=2;//一个满足
	a[0][1]=10;//10月份
	for(i=1;i<=7999;i++)
	{
		year=i+2000;
		cnt=1;
		num[2]=RunYear(year);
		for(j=1;j<=12;j++)//i+1 年
		{
			week=(week+num[temp[j]]%7)%7;
			//printf("%d年%d月13日:星期%d\n",i+2000,j,week);
			if(week%7==5)
				a[i][cnt++]=j;
		}
		a[i][0]=cnt;
	}
	while(~scanf("%d",&n))
	{
		cnt=a[n-2000][0];
		if(cnt==1)printf("Luck\n");
		else
		{
			for(i=1;i<=cnt-2;i++)
				printf("%d ",a[n-2000][i]);
			printf("%d\n",a[n-2000][cnt-1]);
		}
	}
	return 0;
}

发表于 2017-06-02 11:24:53 回复(2)
import java.util.*;
public class Main{
    public static void main(String[]args){
        Scanner scann=new Scanner(System.in);
        while(scann.hasNext()){
            int year=scann.nextInt();
            if(year==2000){
                System.out.println(10);
                continue;
            }else{
                ArrayList<Integer> list=day(year);
                if(list.size()==0){
                    System.out.println("Luck");
                }else{
                    System.out.print(list.get(0));
                    for(int i=1;i<list.size();i++){
                        System.out.print(" "+list.get(i));
                    }
                    System.out.println();
                }
            }
        }
    }
    
    //计算某年第一个13号是星期几
    public static int firstDay(int year){
        int count=5;//2001年的1月13号星期6,由于对7求余是0到6,所以为5
        for(int i=2001;i<year;i++){
            if((i%4==0) && (i%100!=0)||(i%400==0)){//上一年是闰年,366%7=2
                count=(count+2)%7;
            }else{
                count=(count+1)%7;//上一年为平年,365%7=1
            }
        }
        return count;
    }
    
    //计算一年有哪些月满足条件
    public static ArrayList<Integer> day(int year){
        ArrayList<Integer> list=new ArrayList<Integer>();
        int n=firstDay(year);
        if(n==4){
            list.add(1);
        }
        for(int i=1;i<12;i++){
            if(i==1 || i==3 || i==5 || i==7 || i==8 || i==10){
                n=(n+3)%7;
            }else if(i==4 || i==6 || i==9 || i==11){
                n=(n+2)%7;
            }else if((year%4==0&&year%100!=0)||(year%400==0)){
                n=(n+1)%7;
            }
if(n==4){
                list.add(i+1);
            } 
        }
        return list;
    }
}
发表于 2016-07-23 11:20:44 回复(0)
bad_luck_day(List) ->
	ResultList = [bad_luck_day(Year, 1, []) || Year <- List],
	Fun = fun(MonthList) ->
				  [io:format("~p ", [X]) || X <- MonthList],
				  io:format("~n")
		  end,
	lists:foreach(Fun, ResultList).
bad_luck_day(_Year, Num, Result) when Num > 12 ->
	lists:reverse(Result);
bad_luck_day(Year, Num, Result) ->
	Week = calendar:day_of_the_week({Year,Num,13}),
	if
		Week =:= 5 ->
			bad_luck_day(Year, Num+1, [Num|Result]);
		true ->
			bad_luck_day(Year, Num+1, Result)
	end. 

发表于 2016-06-06 14:42:12 回复(0)
啥头像
跟楼上思路一样,用python写的
def whichDay(year, month, day):
    rlt = 0
    month -= 1
    while month>0:
        if month in [1, 3, 5, 7, 8, 10, 12]:
            rlt += 31
        else:
            if month!=2:
                rlt += 30
            else:
                rlt += 28
                if (year%4==0 and year%100!=0) or year%400==0:
                    rlt += 1
        month -= 1
    return (365*(year-1)+((year-1)//4 - (year-1)//100 + (year-1)//400) + rlt + day)

while True:
    try:
        year = input()
        year = int(year)
    except:
        break

    cnt = 0
    rlt = ''
    for month in range(1, 13):
        if (whichDay(year, month, 13)%7) == 5:
            if cnt:
                rlt += ' '
            rlt += str(month)
            cnt += 1
    if cnt:
        print(rlt)
    else:
        print('Luck') 


发表于 2016-01-12 14:44:26 回复(0)