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
  • 相关阅读:
    jsp 特殊标签
    poj 1753 Flip Game 高斯消元 异或方程组 求最值
    zoj 3155 Street Lamp 高斯消元 异或方程组 求方案数
    poj1222 EXTENDED LIGHTS OUT 高斯消元解异或方程组 模板
    zoj 3930 Dice Notation 模拟
    zoj 3157 Weapon 线段树求逆序对数
    hdu 1242 Rescue BFS+优先队列
    hdu 3466 Proud Merchants 贪心+01背包
    zoj 3689 Digging 贪心+01背包
    hdu 2602 Bone Collector 01背包模板
  • 原文地址:https://www.cnblogs.com/Macaulish/p/7358278.html
Copyright © 2011-2022 走看看