Skip to content

11008: 【原1008】二哥买期货

题目

题目描述

author: xjia 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1008

Description

二哥想知道在一段时期内,一共有多少个交易日。期货交易日的限定如下:

  1. 周六、周日不能交易
  2. 元旦期间(1月1日)不能交易
  3. 五一劳动节期间(5月1日至3日)不能交易
  4. 十一国庆节期间(10月1日至7日)不能交易
  5. 没有在上述要求中提到的日期均可交易

Input Format

第一行有一个整数n,表示一共有n组数据。

每组数据都有一行,是两个用空格分开的日期,分别为开始日期和结束日期。日期格式为YYYY-MM-DD(比如2010-11-11);数据保证开始日期不晚于结束日期。

对于所有数据:\( n \leq 365 \)

对于30%的数据:日期范围从2010-11-23至2012-12-21

对于70%的数据:日期范围从1900-01-01至9999-12-31

Output Format

输出共n行,每行一个整数,对应于一组数据。

每组数据需要输出在指定日期区间内,共有多少个交易日;区间的开始和结束日期也算在内(如果是交易日的话)。

Sample Input

4
2010-11-18 2010-11-20
2010-01-01 2010-01-01
2010-05-01 2010-05-03
2010-10-01 2010-10-07

Sample Output

2
0
0
0

FineArtz's solution

/* 二哥买期货 */
#include <iostream>
#include <string>
using namespace std;

bool LeapYear[10000] = {0}, CanTrade[10000][13][32] = {0};
const short Day[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
short Week[10000][13][32] = {0}, CanTradeDays[10000] = {0};

struct Date{
    //constructor
    Date(const string&);
    Date(int, int, int);

    Date& operator ++();
    friend inline bool operator ==(const Date&, const Date&);
    friend inline bool operator !=(const Date&, const Date&);
    int yy, mm, dd;
};
Date::Date(const string& s){
    yy = mm = dd = 0;
    for (int i = 0; i != 4; ++i)
        yy = yy * 10 + s[i] - '0';
    mm = (s[5] - '0') * 10 + s[6] - '0';
    dd = (s[8] - '0') * 10 + s[9] - '0';
}
Date::Date(int y, int m, int d) : yy(y), mm(m), dd(d){}
Date& Date::operator ++(){
    ++dd;
    if (mm != 2){
        if (dd > Day[mm]){
            dd = 1;
            ++mm;
            if (mm > 12){
                mm = 1;
                ++yy;
            }
        }
    }
    else{
        if (dd > (LeapYear[yy] ? 29 : 28)){
            dd = 1;
            mm = 3;
        }
    }
    return *this;
}
inline bool operator ==(const Date& lhs, const Date& rhs){
    return (lhs.yy == rhs.yy && lhs.mm == rhs.mm && lhs.dd == rhs.dd);
}
inline bool operator !=(const Date& lhs, const Date& rhs){
    return !(lhs == rhs);
}

inline int succ(int x) { return ((x + 1) % 7 == 0) ? 7 : ((x + 1) % 7); }

void PreTreatment(){
    for (int i = 1900; i <= 9999; ++i)
        LeapYear[i] = (i % 400 == 0 || (i % 4 == 0 && i % 100 != 0));
    Week[1900][1][1] = 1;
    for (int yy = 1900; yy <= 9999; ++yy){
        int day = 0, lday = 0, year = yy;
        for (int mm = 1; mm <= 12; ++mm)
        {
            if (mm != 2) day = Day[mm];
            else day = (LeapYear[year] ? 29 : 28);
            if (mm > 1) Week[yy][mm][1] = succ(Week[yy][mm - 1][lday]);
            else if (yy != 1900) Week[yy][mm][1] = succ(Week[yy - 1][12][31]);
            for (int dd = 2; dd <= day; ++dd)
                Week[yy][mm][dd] = succ(Week[yy][mm][dd - 1]);
            lday = day;
            day = 0;
        }
    }
    for (int yy = 1900; yy <= 9999; ++yy)
        for (int mm = 1; mm <= 12; ++mm){
            int day;
            if (mm != 2) day = Day[mm];
            else day = (LeapYear[yy] ? 29 : 28);
            for (int dd = 1; dd <= day; ++dd){
                CanTrade[yy][mm][dd] = !((Week[yy][mm][dd] == 6) || (Week[yy][mm][dd] == 7)
                                        || (mm == 1 && dd == 1) || (mm == 5 && dd <= 3) || (mm == 10 && dd <= 7));
                if (CanTrade[yy][mm][dd]) ++CanTradeDays[yy];
            }
        }
}

int gap(const Date& d1, const Date& d2){
    int ret = 0;
    if (d1.yy + 1 >= d2.yy){
        for (Date d(d1.yy, d1.mm, d1.dd); d != d2; ++d)
            if (CanTrade[d.yy][d.mm][d.dd]) ++ret;
        return (CanTrade[d2.yy][d2.mm][d2.dd] ? ++ret : ret);
    }
    for (Date d(d1.yy, d1.mm, d1.dd); d != Date(d1.yy + 1, 1, 1); ++d)
        if (CanTrade[d.yy][d.mm][d.dd]) ++ret;
    for (Date d(d2.yy, 1, 1); d != d2; ++d)
        if (CanTrade[d.yy][d.mm][d.dd]) ++ret;
    if (CanTrade[d2.yy][d2.mm][d2.dd]) ++ret;
    for (int yy = d1.yy + 1; yy != d2.yy; ++yy)
        ret += CanTradeDays[yy];
    return ret;
}

int main(){
    PreTreatment();
    int n;
    cin >> n;
    for (int data = 0; data != n; ++data){
        string s1, s2;
        cin >> s1 >> s2;
        Date date1(s1), date2(s2);
        cout << gap(date1, date2) << endl;
    }
    return 0;
}

ligongzzz's solution

#include <iostream>
#include <stdio.h>
using namespace std;
int dayOfMonth[][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} };
struct Date
{
    int y, m, d;
    int leap()
    {
        return (y % 4 == 0 && y % 100 != 0 || y % 400 == 0 ? 1 : 0);
    }
    int week()
    {
        int Y = y, M = m;
        if (m == 1 || m == 2)
        {
            Y--;
            M += 12;
        }
        int W = (d + M * 2 + 3 * (M + 1) / 5 + Y + Y / 4 - Y / 100 + Y / 400) % 7;
        return W + 1;
    }
    Date() {}
    Date(int yy, int mm, int dd) { y = yy; m = mm; d = dd; }
    Date getNext()
    {
        Date t(y, m, d);
        if (d < dayOfMonth[leap()][m])
            t.d += 1;
        else if (m < 12)
        {
            t.m += 1;
            t.d = 1;
        }
        else
        {
            t.y += 1;
            t.m = 1;
            t.d = 1;
        }
        return t;
    }

    bool dealDay()
    {
        if (week() == 6 || week() == 7)
            return false;
        if (m == 1 && d == 1 || m == 5 && d >= 1 && d <= 3 || m == 10 && d >= 1 && d <= 7)
            return false;
        return true;
    }
    bool isWeekend()
    {
        return week() == 6 || week() == 7;
    }

};
bool equals(Date d1, Date d2)
{
    return d1.y == d2.y && d1.m == d2.m && d1.d == d2.d;
}

int ansOfYear(int year)
{
    bool isleap = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
    int res = (isleap ? 366 : 365), t1, t2, t3 = 0, i;
    t1 = 104;
    if (isleap)
    {
        if (Date(year, 12, 30).isWeekend())
            t1 += 1;
        if (Date(year, 12, 31).isWeekend())
            t1 += 1;
    }
    else
    {
        if (Date(year, 12, 31).isWeekend())
            t1 += 1;
    }
    t2 = 11;
    if (Date(year, 1, 1).isWeekend())
        t3 += 1;
    for (i = 1; i < 4; i++)
        if (Date(year, 5, i).isWeekend())
            t3 += 1;
    for (i = 1; i < 8; i++)
        if (Date(year, 10, i).isWeekend())
            t3 += 1;
    res = res - t1 - t2 + t3;
    return res;
}

int main()
{
    int n, res = 0, i;
    Date d1, d2, t;
    scanf("%d", &n);
    while (n--)
    {
        res = 0;
        scanf("%d-%d-%d %d-%d-%d", &d1.y, &d1.m, &d1.d, &d2.y, &d2.m, &d2.d);
        if (d2.y - d1.y <= 1)
        {
            for (t = d1; !equals(t, d2.getNext()); t = t.getNext())
                if (t.dealDay())
                    res += 1;
        }
        else
        {
            for (t = d1; !equals(t, Date(d1.y + 1, 1, 1)); t = t.getNext())
                if (t.dealDay())
                    res += 1;
            for (t = Date(d2.y, 1, 1); !equals(t, d2.getNext()); t = t.getNext())
                if (t.dealDay())
                    res += 1;
            for (i = d1.y + 1; i < d2.y; i++)
                res += ansOfYear(i);
        }
        printf("%d\n", res);
    }
    return 0;
}

yyong119's solution

#include <iostream>
using namespace std;
int monthDays[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
struct date {
    int year;
    int month;
    int day;
    int dayForWeek;
};


int getWeek(const date &d) {
    int m = d.month, y = d.year;
    if(d.month <= 2) {
        m += 12;
        --y;
    }
    int dayForWeek = (d.day + 2 + 2 * m + 3 * (m + 1) / 5 - 1 + y + y / 4 - y / 100 + y / 400) % 7;
    return dayForWeek;
}

int countDays(const date& d1, const date& d2) {
    bool isLeap(int);
    int count = 0, month, year;
    if(d1.year == d2.year)
        if(d1.month == d2.month)
            return (d2.day - d1.day + 1);
        else  {
            count = monthDays[d1.month] - d1.day + 1 + d2.day;
            for (month = d1.month + 1; month < d2.month; ++month) count += monthDays[month];
            if (2 >= d1.month && 2 < d2.month && isLeap(d1.year)) ++count;
            return count;
        }
    else {
        date d3 = {d1.year, 12, 31}, d4 = {d2.year, 1, 1};
        count = countDays(d1, d3) + countDays(d4, d2);
        for(year = d1.year + 1; year < d2.year; ++year) {
            count += 365;
            if(isLeap(year)) ++count;
        }
        return count;
    }
}

bool isLeap(int year) {
    return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}

bool betwDays(date &d1,date &d2,date &d3) {

    if (d1.year < d3.year && d3.year < d2.year) return true;
    else if(d3.year < d1.year || d3.year > d2.year) return false;
    else if(d3.year == d1.year)
        if(d1.year == d2.year) {
            if(d1.month < d3.month && d3.month < d2.month) return true;
            else if(d3.month < d1.month || d3.month > d2.month) return false;
            else if(d3.month == d1.month)
                if(d1.month == d2.month)
                    if(d1.day <= d3.day && d3.day <= d2.day)return true;
                    else return false;
                else
                    if(d3.day >= d1.day) return true;
                    else return false;
            else
                if(d3.day <= d2.day)return true;
                else return false;
        }
        else {
            date d4 = {d1.year, 12, 31};
            return (betwDays(d1, d4, d3));
        }
    else {
        date d4 = {d2.year, 1, 1};
        return (betwDays(d4, d2, d3));
    }
}

void dayUp(date &d) {
    bool isLeap(int);
    ++d.day;
    if(d.day > monthDays[d.month] + (d.month == 2 && isLeap(d.year))) {
        d.day=1;
        ++d.month;
        if(d.month > 12) {
            d.month = 1;
            ++d.year;
        }
    }
    ++d.dayForWeek;
    if(d.dayForWeek > 6) d.dayForWeek = 0;
}

int main() {

    date d1, d2, dtemp;
    char eat;
    int n, *p, i, j, daysNum, holidays, year;
    cin >> n;
    p = new int[n];
    for(i = 0; i < n; ++i) {
        cin >> d1.year >> eat >> d1.month >> eat >> d1.day;
        cin >> d2.year >> eat >> d2.month >> eat >> d2.day;
        d1.dayForWeek = getWeek(d1);
        d2.dayForWeek = getWeek(d2);
        daysNum = countDays(d1, d2);
        holidays = daysNum / 7 * 2;
        for(dtemp = d1, j = 0; j < daysNum % 7; ++j) {
            if(dtemp.dayForWeek == 0 || dtemp.dayForWeek == 6) ++holidays;
            dayUp(dtemp);
        }
        for(year = d1.year; year <= d2.year; ++year) {
            dtemp.year = year;
            dtemp.month = dtemp.day = 1;
            dtemp.dayForWeek = getWeek(dtemp);
            if(year != d1.year && year != d2.year || betwDays(d1, d2, dtemp))
            holidays += (dtemp.dayForWeek != 0 && dtemp.dayForWeek != 6);
            dtemp.month = 5;
            dtemp.day = 1;
            dtemp.dayForWeek = getWeek(dtemp);
            for(j = 0; j < 3; ++j) {
                if(year != d1.year && year != d2.year || betwDays(d1, d2, dtemp))
                    holidays += (dtemp.dayForWeek != 0 && dtemp.dayForWeek != 6);
                dayUp(dtemp);
            }
            dtemp.month = 10;
            dtemp.day = 1;
            dtemp.dayForWeek = getWeek(dtemp);
            for(j = 0; j < 7; ++j) {
                if(year != d1.year && year != d2.year || betwDays(d1, d2, dtemp))
                    holidays += (dtemp.dayForWeek != 0 && dtemp.dayForWeek != 6);
                dayUp(dtemp);
            }
        }
        p[i] = daysNum - holidays;
    }
    for(i = 0; i < n; ++i) cout << p[i] << endl;
    delete [] p;
    return 0;
}