zoukankan      html  css  js  c++  java
  • 【hdu6093】Rikka with Number

    多校第五場的題。

    首先是一個好數只在某個進制下,不會是在兩個進制下都爲好數。

    另外每個進制好數的個數爲d!-(d-1)!,因爲要保證第一位不爲0.

    然後就是在臨界進制下有多少個好數的問題,可以變成兩個子問題,一個是找到小於n的第一個排列數,第二個是排列數的排名。

    康託展開修改一下就可以變成求這兩個問題。

    具體來說就是對於某個位的數字,比它小且不在前面出現的數字作爲當前位時後面無論怎麼擺都會小於這個數,so個數×剩下位數的階乘就是排名再增加的。

    最後一位要+1,第一位不能爲0。區別在於如果現在的數字是前面出現過的數字,直接break掉。

    比賽的時候口胡了一下,後來覺得麻煩就否決掉了23333.

    其實沒有多複雜。

    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define rep(i,l,r) for(int i=l;i<=r;i++)
    #define dow(i,l,r) for(int i=r;i>=l;i--)
    #define rep0(i,r) for(int i=0;i<r;i++)
    #define repedge(i,x)
    #define maxn 50010
    #define LL long long
    using namespace std;
    
    const LL mm=998244353;
    int a[maxn],b[maxn],c[maxn],num[maxn],n,len,len2;
    LL f[maxn];
    char s[maxn];
    double maxd[maxn];
    
    
    void change(char *s)
    {
        len=strlen(s);
        rep0(i,len) a[len-i-1]=s[i]-'0';
    }
    
    void small(int *a)
    {
        a[0]--;
        rep(i,0,len-1)
            if (a[i]<0) {
                a[i+1]--;
                a[i]+=10;
            }
            else break;
        while (len && !a[len-1]) len--;
    }
    
    void tobe(int m)
    {
        len2=0;
        rep0(i,len) c[i]=a[i];
        int len1=len;
        while (len1) {
            int now=0;
            dow(i,0,len1-1) {
                now=(now*10+c[i]);
                c[i]=now/m;
                now%=m;
            }
            b[len2++]=now;
            if (len2>m) break;
            while (len1 && !c[len1-1]) len1--;
        }
    }
    
    LL ask(int m)
    {
        tobe(m);
        if (len2>m) return (f[m]-f[m-1]+mm)%mm;
        if (len2<m) return 0;
        rep0(i,m) num[i]=0;
        LL ans=-f[m-1];
        dow(i,0,m-1) {
            rep0(j,b[i])
                if (!num[j]) ans=(ans+f[i])%mm;
            if (num[b[i]]) break;
            num[b[i]]=1;
            if (!i) ans++;
        }
        return ans;
    }
    
    LL calc()
    {
        LL sum=0;
        int now;
        for(now=2;maxd[now+1]<=len-1;now++);
        if (now>2) sum=(f[now-1]-1+mm)%mm;
        LL more=ask(now)+ask(now+1);
        sum=(sum+more)%mm;
        return sum;
    }
    
    int main()
    {
        int tt;
    //    freopen("1009.in","r",stdin);
     //   freopen("1.out","w",stdout);
        scanf("%d",&tt);
        f[0]=1;
        for(int i=1;i<=maxn;i++) {
            f[i]=f[i-1]*(LL)i%mm;
            maxd[i]=log(i)*(i-1)/log(10);
        }
        while (tt--) {
            scanf("%s",s);
            change(s);
            small(a);
            LL ans=-calc();
            scanf("%s",s);
            change(s);
            ans=((ans+calc())%mm+mm);
            printf("%lld
    ",ans%mm);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python2.7_1.4_将IPV4地址转换成不同的格式
    大型网站问题的解决方案
    大型网站的标准
    SCP服务实现Linux交互
    SCP服务实现Linux交互
    使用Linux系统中的SSH服务
    向php文件中添加php.ini文件
    让apache与mysql随着系统自动启动
    为apache与mysql创建快捷方式
    安装PHP软件
  • 原文地址:https://www.cnblogs.com/Macaulish/p/7358278.html
Copyright © 2011-2022 走看看