• Codeforces Round #359 (Div. 2) C. Robbers' watch


    题目链接:传送门

    题目大意:有一只表,由7进制表示,你将一天分为n个小时,将一小时分为m分钟,要求表上显示的数字各不相同,问在n,m的限制下有多少种合法的时间表示

         例如 n=2,m=3 (0: 1), (0: 2), (1: 0), (1: 2).  n=8,m=2 (02: 1), (03: 1), (04: 1), (05: 1), (06: 1).

    题目思路:因为是由7进制表示,所以手表上显示的数字不能超过7个,否则必然有重复的(不合法),因此我们只需要特判一下,然后dfs即可。

         这个题还是比较可惜的,当时晚上没做出来,早上起来发现边界情况有点问题,改了一下就过了,自己还是太弱。。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <stack>
    #include <cctype>
    #include <queue>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <climits>
    #define lson root<<1,l,mid
    #define rson root<<1|1,mid+1,r
    #define fi first
    #define se second
    #define ping(x,y) ((x-y)*(x-y))
    #define mst(x,y) memset(x,y,sizeof(x))
    #define mcp(x,y) memcpy(x,y,sizeof(y))
    using namespace std;
    #define gamma 0.5772156649015328606065120
    #define MOD 1000000007
    #define inf 0x3f3f3f3f
    #define N 100005
    #define maxn 1005
    typedef pair<int,int> PII;
    typedef long long LL;
    
    int n,m,k,x,num,y;
    int vis[10],ans;
    void dfs2(int sum,int cnt){ ///dfs2处理分钟段(m),其他和dfs1同理
        if(sum>=m)return;
        if(cnt==y){++ans;return;}
        for(int i=0;i<7;++i){
            if(!vis[i]){
                vis[i]=1;
                sum=sum*7+i;
                dfs2(sum,cnt+1);
                sum=(sum-i)/7;
                vis[i]=0;
            }
        }
    }
    void dfs1(int sum,int cnt){///dfs1处理小时段(n),sum表示当前时间(sum<n),
        if(sum>=n)return ;     ///cnt表示已经处理了几位数字
        if(cnt==x){
            for(int j=0;j<7;++j)if(!vis[j]){
                vis[j]=1;
                dfs2(j,1);
                vis[j]=0;
            }
        }
        for(int i=0;i<7;++i){
            if(!vis[i]){
                vis[i]=1;
                sum=sum*7+i;
                dfs1(sum,cnt+1);
                sum=(sum-i)/7;
                vis[i]=0;
            }
        }
    }
    int deal(int x){    ///特殊处理,返回表示n,m需要多少位数字
        int cnt=0;
        while(x){
            ++cnt;
            x=x/7;
        }
        return cnt;
    }
    int main(){
        int i,j,group,v;
        scanf("%d%d",&n,&m);
        if(n%7==0)x=deal(n-1);///这里需要注意,如果n能被7整除
        else x=deal(n);       ///那么表示n所需要的数字位数要减一,也就是这没考虑清楚,很可惜。
        if(m%7==0)y=deal(m-1);///m同理处理
        else y=deal(m);
        if(x+y>7){exit(0*printf("0
    "));}
        for(i=0;i<7;++i){
            vis[i]=1;
            dfs1(i,1);
            vis[i]=0;
        }
        printf("%d
    ",ans);
        return 0;
    }

     看了下官方题解,发现其实有更简便的思想

    用一个used数组,记录0~6这7个数字使用情况,然后小时从0枚举到n-1,分钟从0枚举到m-1,如果used数组使用情况合法ans++

    不过好像比上面的搜索要慢一些(搜索15ms,枚举46ms)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <stack>
    #include <cctype>
    #include <queue>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <climits>
    #define lson root<<1,l,mid
    #define rson root<<1|1,mid+1,r
    #define fi first
    #define se second
    #define ping(x,y) ((x-y)*(x-y))
    #define mst(x,y) memset(x,y,sizeof(x))
    #define mcp(x,y) memcpy(x,y,sizeof(y))
    using namespace std;
    #define gamma 0.5772156649015328606065120
    #define MOD 1000000007
    #define inf 0x3f3f3f3f
    #define N 100005
    #define maxn 1005
    typedef pair<int,int> PII;
    typedef long long LL;
    
    int n,m,k,x,num,y;
    int vis[10],ans;
    
    int deal(int x){    ///特殊处理,返回表示n,m需要多少位数字
        int cnt=0;
        while(x){
            ++cnt;
            x=x/7;
        }
        return cnt;
    }
    int used[10];
    int main(){
        int i,j,group,v;
        scanf("%d%d",&n,&m);
        if(n%7==0)x=deal(n-1);
        else x=deal(n);
        if(m%7==0)y=deal(m-1);
        else y=deal(m);
        if(x+y>7){exit(0*printf("0
    "));}
        for(i=0;i<n;++i){
            for(j=0;j<m;++j){
                mst(used,0);
                int t1=i,cnt=0;
                while(cnt++<x){
                    ++used[t1%7];
                    t1/=7;
                }
                t1=j;cnt=0;
                while(cnt++<y){
                    ++used[t1%7];
                    t1/=7;
                }
                if(*max_element(used,used+7)<=1)++ans;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Cognos无法解密来着内容库的用户名和密码凭证
    JavaScript 中的对象引用
    npm install出现的错误
    箭头函数中this的用法
    [译]ArcGIS Server Map Service Cache的组织结构
    [C#] 如何选择抽象基类与接口
    数据库设计规范
    在DataTable中查询应该注意的问题
    坦克大战总结
    仓库管理系统总结(1)
  • 原文地址:https://www.cnblogs.com/Kurokey/p/5612981.html
Copyright © 2020-2023  润新知