zoukankan      html  css  js  c++  java
  • bzoj4980: 第一题

    Description

    神犇xzyo听说sl很弱,于是出了一题来虐一虐sl。一个长度为2n(可能有前缀0)的非负整数x是good的,当且仅当
    存在两个长度为n(可能有前缀0)的非负整数a、b满足a+b==10n,并且对于0~9每个数位d,都有Sd(x)==Sd(a)+Sd(
    b)(Sd(x)为x的十进制中d出现了多少次)。例如0829是good的,98+02==100。给出一个长度为2n的序列,其中有些
    位置是问号。将每个问号替换为0~9任意一个数位后,有多少个good数,答案对1000000007取膜。为了sl不被虐死
    ,快告诉他怎么写吧。
    两个数相加为10^n,意味着可以将数位一部分按09,18,27,36,45配对表示较高位的情况,低位有一对19,28,37,46,55产生了一次进位,更低位可以全0。枚举哪一对数产生进位,可以算出0的出现次数-9的出现次数,1-8,2-7,3-6,4-5的值,然后做一次背包。需要特判一些情况:因为两个0可以配对,0-9的值表示的是0至少比9多几个,实际可以再把一些9换成0,但如果19产生进位,必须留下至少一个9(可能来自已确定的数位,也可能必须由?提供)而不能全部换成0。
    #include<bits/stdc++.h>
    typedef long long i64;
    const int P=1e9+7;
    char s[100007];
    int n,t[11],m=0,ts[11];
    i64 f[1007],g[1007],fac[1007],fiv[1007],ans=0;
    i64 _ks[2077][1007],(*ks)[1007]=_ks+1027;
    bool d9=0;
    void cal(int tp){
        memset(f,0,sizeof(f));
        f[0]=1;
        for(int i=0;i<5;++i){
            memset(g,0,sizeof(g));
            if(ts[i]>m||i&&ts[i]<-m)return;
            if(!i){
                while(ts[i]<-m)ts[i]+=2;
                for(int s=0,d=0;s<=m;++s){
                    i64 iv=ks[ts[i]][s];
                    if(!iv)continue;
                    if(tp==1&&!d9&&(s+ts[i])%2==0)iv=(iv-fiv[s]+P)%P;
                    for(int j=s;j<=m;++j)g[j]+=f[j-s]*iv;
                    if(++d>6){
                        d=0;
                        for(int j=0;j<=m;++j)g[j]%=P;
                    }
                }
            }else for(int a=ts[i],b=0,d=0;a+b<=m;++a,++b)if(a>=0){
                int s=a+b;
                i64 iv=fiv[a]*fiv[b]%P;
                for(int j=s;j<=m;++j)g[j]+=f[j-s]*iv;
                if(++d>6){
                    d=0;
                    for(int j=0;j<=m;++j)g[j]%=P;
                }
            }
            for(int j=0;j<=m;++j)f[j]=g[j]%P;
        }
        ans=(ans+f[m]*fac[m])%P;
    }
    i64 pw(i64 a,int n){
        i64 v=1;
        for(;n;n>>=1,a=a*a%P)if(n&1)v=v*a%P;
        return v;
    }
    int main(){
        for(int i=fac[0]=1;i<=1000;++i)fac[i]=i*fac[i-1]%P;
        fiv[1000]=pw(fac[1000],P-2);
        for(int i=1000;i;--i)fiv[i-1]=i*fiv[i]%P;
        scanf("%s",s);
        n=strlen(s);
        if(n&1)return puts("0"),0;
        for(int i=0;i<n;++i){
            if(s[i]=='?')++m;
            else ++t[s[i]-'0'];
            d9|=s[i]=='9';
        }
        for(int i=m;i>=-m;--i){
            for(int a=i,b=0;a+b<=m;++a,++b)if(a>=0)ks[i][a+b]=fiv[a]*fiv[b]%P;
            for(int j=0;j<=m;++j)ks[i][j]=(ks[i][j]+ks[i+2][j])%P;
        }
        for(int i=1;i<=5;++i){
            for(int j=0;j<10;++j)ts[j]=t[j];
            --ts[i],--ts[10-i];
            for(int j=0;j<5;++j)ts[j]=ts[9-j]-ts[j];
            i64 a0=ans;
            cal(i);
            a0=ans-a0;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    jquery获取input的checked属性
    归并排序法
    Pascal's Triangle II —LeetCode
    01背包之求第K优解——Bone Collector II
    Intellij IDEA 14隐藏被排除的文件夹
    LeetCode——Majority Element
    多线程爬虫Java调用wget下载文件,独立线程读取输出缓冲区
    LeetCode——Restore IP Addresses
    LeetCode——Pascal's Triangle
    LeetCode——Permutations
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7394939.html
Copyright © 2011-2022 走看看