zoukankan      html  css  js  c++  java
  • 荔枝丹(litchi)

    【from new_dtoj 3979: 荔枝丹(litchi)】
    题目描述
    绛雪艳浮红锦烂,玉壶光莹水晶寒。
    高名已许传新曲,芳味曾经荐大官。
    乌府日长霜署静,几株斜覆石栏杆。
    ——明·陈辉《荔枝》

    荔枝(丹),拼音为lizhidan,一种好吃的水果,深得悦色老师的喜爱。
    祝阿姨得到了许多许多的荔枝丹,每个荔枝丹上都有一个0到9之间的数字。祝阿姨把它们分成许多组,每组表示一个数,且所有组表示的数字合起来恰好是[L,R]内的所有数。
    祝阿姨知道悦色老师特别喜欢吃荔枝丹,于是邀请了悦色老师来吃荔枝丹。悦色老师最喜欢吃有数字0的荔枝丹了,她吃掉了所有数字为0的荔枝丹。
    祝阿姨想知道还剩下多少不同的组。注意悦色老师吃完后,荔枝丹就无序了,也就是说123和321是同样的组。
    其中R<=1e18
    题解:
    妙啊!
    如果补上前缀0,使得所有数字位数相等,并把数字看成字符串,并把字符排序,那么问题等价于有多少不同的字符串。
    如果R=1e18,特判即可即L<=R<1e18
    因为不同字符串的数目不是很多(C(27,9)=4686824),所以我们可以暴力求出每个字符串,然后快速判断这个字符串能否被[L,R]中的某个数构造出来
    Fp,lf,rfF_{p,lf,rf}表示到了第p位,前面的位数为L/R的前缀能否满足
    LiL_i表示L第i位的数字(从高到低),RiR_i类似
    分类讨论即可,下面举lf=rf=1的情况

    1. 如果LpL_p==RpR_p,那么第p位上只能填上LpL_p,判断合法往下递归即可
    2. 否则LpL_p<RpR_p,如果在第p位上填上[Lp+1,Rp1][L_p+1,R_p-1],则这个字符串一定满足,否则就看这一位上填的是LpL_p还是RpR_p,有一方满足即满足

    剩下两类也是一样的,懒得分了
    效率玄学,不懂为啥很快?(dtoj评测机强大)
    具体见代码

    #include <cstdio>
    #include <algorithm>
    #define LL long long
    #define I inline
    using namespace std;
    LL l,r;int pl[20],pr[20],c[12],n;
    I bool F(int x,bool L,bool R){
        if (x==19) return 1;
        bool P=0;
        if (L && R){
            if (pl[x]==pr[x]){
                if (!c[pl[x]]) return 0;
                c[pl[x]]--;P=F(x+1,1,1);
                c[pl[x]]++;return P;
            }
            for (int i=pl[x]+1;i<=pr[x]-1;i++) if (c[i]) return 1;
            if (c[pl[x]]) c[pl[x]]--,P|=F(x+1,1,0),c[pl[x]]++;
            if (c[pr[x]]) c[pr[x]]--,P|=F(x+1,0,1),c[pr[x]]++;
            return P;
        }
        else if (L){
            for (int i=pl[x]+1;i<=9;i++) if (c[i]) return 1;
            if (c[pl[x]]){
                c[pl[x]]--;P=F(x+1,1,0);
                c[pl[x]]++;return P;
            }
            else return 0;
        }
        else{
            for (int i=0;i<=pr[x]-1;i++) if (c[i]) return 1;
            if (c[pr[x]]){
                c[pr[x]]--;P=F(x+1,0,1);
                c[pr[x]]++;return P;
            }
            else return 0;
        }
    }
    I void D(int x,int t){
        if (x==19){n+=F(1,1,1);return;}
        for (int i=t;i<=9;i++) c[i]++,D(x+1,i),c[i]--;
    }
    int main(){
        scanf("%lld%lld",&l,&r);
        LL ll=l,rr=r;if (r==(LL)1e18) rr--,c[1]=1,c[0]=17,n+=(!F(1,1,1)),c[1]=0,c[0]=0;
        for (int i=1;i<=18;i++) pl[i]=ll%10,pr[i]=rr%10,ll/=10,rr/=10;
        for (int i=1;i<=9;i++) swap(pl[i],pl[18-i+1]),swap(pr[i],pr[18-i+1]);
        D(1,0);return printf("%d
    ",n),0;
    }
    
  • 相关阅读:
    使用C#中的DirectorySearcher来获得活动目录中的组织结构与用户等信息,并在展示成树形结构(附源代码)
    oracle的简单操作和要注意的地方
    lambda匿名函数
    Linux查看系统信息(版本、cpu、raid)
    chmod 777后,目录权限不可写解决方法
    linux /boot空间满了如何清理
    k3s
    IDEA项目编译参数Werror设置
    minicube 安装
    ubuntu安装docker
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10544724.html
Copyright © 2011-2022 走看看