zoukankan      html  css  js  c++  java
  • 牛客多校第六场 G Is Today Friday? 蔡勒公式/排列

    题意:

    有一堆日期,这些日期都是星期五,但是数字被映射成了字母A~J,现在让你求逆映射,如果存在多种答案,输出字典序最小的那个。

    题解:

    用蔡勒公式解决关于星期几的问题。

    对于映射,可以用笔者刚刚学会的神器,next_permutation(),直接按照字典序生成排列数作为映射,一旦找到解,就输出,必定是字典序最小的。

    理论上,枚举10个排列数需要枚举10!≈3e6次,生成下一个排列复杂度为O(n),每次枚举还要检查1e5个日期。

    但是一旦找到合法的映射便可直接输出,而不合法的映射往往在检查前几个日期时就被检查出不合法,因此剪枝效果还是很好的。

    注意要对于日期去重,对于去重来说unique()是个神器,能直接在排好序的数组上将重复元素只保留一个,然后返回去重之后的数组的最后一位的后一位的地址。参数也是类似于sort()

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    string date[100005];
    char tmp[20];
    //char week[10000][13][32];
    int refl[15];
    inline bool Leap(int year){
        if(year%400==0||(year%4==0 && year%100!=0))return 1;
        else return 0;
    }
    inline bool days31(int month){
        return (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12);
    }
    inline bool Zeller(int year,int month,int day){
        if(year<1600)return 0;
        if(month==0 || month >=13)return 0;
        if(day<=0)return 0; 
        if(month==2){
            if(Leap(year)){
                if(day>29)return 0;
            }else{
                if(day>28)return 0;
            }
        }
        if(days31(month)){
            if(day>31)return 0;
        }else{
            if(day>30)return 0;
        }
        //判断日期合法性 
        if (month == 1 || month == 2){
            year--;month += 12;
        }
        //判断month是否为1或2 
        int c = year / 100;
        int y = year - c * 100;
        int week = y + y / 4 + c / 4 - 2 * c + 26 * (month + 1) / 10 + day - 1;
        week%=7;
        week+=7;
        week%=7;
        return (week==5);
    } 
    int main(){
        int T;
        scanf("%d",&T);
        for(int I=1;I<=T;I++){
            int n;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%s",tmp);
    //            0000/00/00
                tmp[4]=0;
                tmp[7]=0;
                date[i].clear();
                date[i]+=tmp;
                date[i]+=tmp+5;
                date[i]+=tmp+8;
            }
            sort(date+1,date+1+n);
            n=unique(date+1,date+1+n)-date-1;
            //去重 
    //        printf("%d
    ",n);
            for(int i=0;i<10;i++)refl[i]=i;
            bool flag;
            while(1){
                flag=1;
                for(int i=1;i<=n;i++){
                    if(Zeller(
                    refl[date[i][0]-'A']*1000+
                    refl[date[i][1]-'A']*100+
                    refl[date[i][2]-'A']*10+
                    refl[date[i][3]-'A'],
                    refl[date[i][4]-'A']*10+
                    refl[date[i][5]-'A'],
                    refl[date[i][6]-'A']*10+
                    refl[date[i][7]-'A']
                    )==0){
                        flag=0;
                        break;
                    }
                }
                if(flag==1){
                    printf("Case #%d: ",I);
                    for(int i=0;i<10;i++)printf("%d",refl[i]);
                    printf("
    ");
                    break;
                }else{
                    if(!next_permutation(refl,refl+10))break;
                }
            }
            if(flag==0)printf("Case #%d: Impossible
    ",I);
        }
        return 0;
    }

    PS:蔡勒公式的巧妙之处在于它把1,2月当作去年的13,14月,因此将复杂的置闰放到了年底,简化了计算。

  • 相关阅读:
    文件操作一写操作
    文件操作一读操作
    python基础初识
    while循环和格式化输出
    python基础数据类型一(整数类型和布尔值)
    CentOS 6下安装nodejs 0.9.0(转)
    CentOS安装Python教程
    Discuz! X2.5数据库字典(转)
    SQL 语句中的union操作符
    thinkphp空操作和配置文件实现简化路由
  • 原文地址:https://www.cnblogs.com/isakovsky/p/11300375.html
Copyright © 2011-2022 走看看