14980: 第一题

#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\n",ans);
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值