SJTUOJ 1008. 二哥買期貨
阿新 • • 發佈:2018-12-23
問題內容
Description
二哥想知道在一段時期內,一共有多少個交易日。期貨交易日的限定如下:
週六、週日不能交易
元旦期間(1月1日)不能交易
五一勞動節期間(5月1日至3日)不能交易
十一國慶節期間(10月1日至7日)不能交易
沒有在上述要求中提到的日期均可交易
Input Format
第一行有一個整數n,表示一共有n組資料。
每組資料都有一行,是兩個用空格分開的日期,分別為開始日期和結束日期。日期格式為YYYY-MM-DD(比如2010-11-11);資料保證開始日期不晚於結束日期。
對於所有資料:n≤365n≤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
程式碼實現及分析
思路一:將每年按節日劃分為三段XXXX-01-01至XXXX-04-30,XXXX-05-01至XXXX-09-01,XXXX-10-01至XXXX-12-31分別計算天數,再對起始日期進行判斷,如果是交易日就加回來。
#include <stdio.h>
#include <string.h>
int dayos[8099];
int get_doy(int yyyy,int mm,int dd)
{
int isLeap = (!(yyyy % 4) && (yyyy % 100)) || !(yyyy % 400);
int doy = 0,moy;
int mds[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
for(moy = 0; moy < mm - 1; moy++){
doy + = mds[moy]+((1==moy&&isLeap)?1:0);
}
doy += dd;
return doy;
}
int judge(int dayo, int emm, int edd, int toy){
if( 1 == emm && 1 == edd ){
return 0;
}
if( 5 == emm && 1 <= edd && 3 >= edd){
return 0;
}
if( 10 == emm && 1 <= edd && 7 >= edd){
return 0;
}
if((dayo+toy-1) % 7 > 4){
return 0;
}
return 1;
}
int main()
{
int n;
int syyyy,smm,sdd,eyyyy,emm,edd;
int tyyyy;
int foy,toy,soy,eoy;
int isLeap = 0, dayo = 0;
int daycnt = 0,i,tempcnt,daystart,leftdays,alldays;
int semap[3][4]={{1,1,4,30},{5,3,9,30},{10,7,12,31}};
dayos[0] = 0;
for(i = 0;i < 8099;i++){
isLeap = (!((i+1900) % 4) && ((i+1900) % 100)) || !((i+1900) % 400);
dayos[i+1] = (dayos[i] + (isLeap?366:365))%7;
}
scanf("%d", &n);
while(n--){
scanf("%d-%d-%d %d-%d-%d",&syyyy,&smm,&sdd,&eyyyy,&emm,&edd);
daycnt = 0;
foy = get_doy(syyyy,smm,sdd);
toy = get_doy(eyyyy,emm,edd);
for(tyyyy=syyyy;tyyyy <= eyyyy;tyyyy++){
dayo=dayos[tyyyy-1900];
for(i = 0; i < 3; i++){
soy = get_doy(tyyyy,semap[i][0],semap[i][1]);
eoy = get_doy(tyyyy,semap[i][2],semap[i][3]);
if(tyyyy == syyyy)
{
if(foy > eoy){
continue;
}
else if(foy > soy && foy <= eoy)
{
soy = foy;
}
}
if(tyyyy == eyyyy)
{
if(toy < soy){
continue;
}
else if(toy >= soy && toy < eoy){
eoy = toy;
}
}
tempcnt = eoy - soy;
daystart = (dayo + soy)%7;
alldays = daystart + tempcnt;
leftdays = alldays % 7;
tempcnt = (alldays / 7) * 5 - (daystart > 4 ? 5:daystart) + (leftdays > 4 ? 5:leftdays);
daycnt += tempcnt;
}
}
//Judge if toy is weekday
daycnt += judge(dayos[syyyy-1900],smm,sdd,foy);
printf("%d\n",daycnt);
}
return 0;
}
這種方法分段內容太多所以效率較低:時間531ms 空間:9344kb
思路二:整段計算前後天數再將所有節日判斷後剔除。
// 暫略