zoj 3939 The Lucky Week(打表找循环节)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3939 

题意:给你一个定义,幸运周,如果周一是某个月的1号,11号或者21号,那么这周就是幸运周,然后问你第n个幸运周的周一是哪天

题解:这题主要要想到n很大, 所以肯定有循环,因为有闰年,导致开头一些日子会不一样,但是有4年闰和400年闰,他们的lcm是400,所以想到400年应该是一个周期(不一定最小),所以可以直接打表得到400年内的lucky week的个数为2058个,然后取模,模拟就行了

wa了很久因为发现题目里输入是1753-9999,而不是答案范围才9999以内。找到n%2058个break就行了,不需要考虑别的

以前一直用paste,感觉是时候每题都贴出来了,多做记录

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           100005
#define   MAXN          1000005
#define   maxnode       10
#define   sigma_size    2
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-9;
const LL     mod   = 1e9+7;
const ull    mxx   = 1333331;

/*****************************************************/
inline void RI(int &x){
    char c;
    while((c=getchar())<'0' || c>'9');
    x=c-'0';
    while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/

int str_week(int y,int m,int d){
    int a=7; // 用来保存计算得到的星期几的整数
    int  str_date;
    if((m==1)||(m==2)){
        m+=12;
        y--;
    }
    a=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;   //得到的星期几的整数
    switch (a){
    case 0:
        str_date=1;
        break;
    case 1:
        str_date=2;
        break;
    case 2:
        str_date=3;
        break;
    case 3:
        str_date=4;
        break;
    case 4:
        str_date=5;
        break;
    case 5:
        str_date=6;
        break;
    case 6:
        str_date=7;
        break;
    }
    return str_date;
}

int main(){
    //freopen("in.txt","r",stdin);
    int t;
    cin>>t;
    //dabiao();
    while(t--){
        int y,m,d,n;
        cin>>y>>m>>d>>n;
        int k=(n/2058)*400;
        n%=2058;
        if(n==0){
            n+=2058;
            k-=400;
        }
        //cout<<n<<endl;
        int tmp=0;
        y+=k;
        int yy=y;
        int flag=0;
        while(1){
            int mm=1;
            if(yy==y){
                mm=m;
            }
            while(mm<=12){
                int dd=1;
                if(yy==y&&mm==m){
                    dd=d;
                }
                while(dd<30){
                    if(str_week(yy,mm,dd)==1){
                        tmp++;
                        if(tmp==n){
                            printf("%d %d %d\n",yy,mm,dd);
                            flag=1;
                            break;
                        }
                    }
                    dd+=10;
                }
                mm++;
                if(flag) break;
            }
            yy++;
            if(flag) break;
        }

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值