[GDKOI2016]QT与泰剧

题目大意

给定高精度数S和T,求出T+1~S中所有满足对模3与S同余且每一位皆不为质数的数的个数。

数位DP

裸的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10,mo=10007;
int pri[5];
int a[maxn],b[maxn],c[maxn],d[maxn];
int f[maxn][4][2][2];
int i,j,k,l,t,n,m,ans,x,y,z;
bool czy;
char ch;
char get(){
    char ch=getchar();
    while (ch!=' '&&(ch<'0'||ch>'9')) ch=getchar();
    return ch;
}
int main(){
    pri[1]=2;pri[2]=3;pri[3]=5;pri[4]=7;
    while (1){
        ch=get();
        if (ch==' ') break;
        a[++n]=ch-'0';
    }
    z=0;
    fo(i,1,n){
        z=z*10+a[i];
        z%=3;
    }
    while (1){
        ch=getchar();
        if (ch<'0'||ch>'9') break;
        b[++m]=ch-'0';
    }
    fd(i,n,n-m+1) b[i]=b[i-(n-m)];
    fd(i,n-m,1) b[i]=0;
    b[n]++;
    i=n;
    while (b[i]>9){
        b[i]=0;
        b[--i]++;
    }
    fd(i,n,1){
        c[i]=c[i]+a[i]-b[i];
        if (c[i]<0){
            c[i]+=10;
            c[i-1]--;
        }
    }
    j=0;
    fo(i,1,n){
        j=j*10+c[i];
        d[i]=j/3;
        j%=3;
    }
    d[n]++;
    i=n;
    while (d[i]>9){
        d[i]=0;
        d[--i]++;
    }
    j=0;
    fo(i,1,n){
        j=j*10+d[i];
        j%=mo;
    }
    ans=j;
    y=0;
    czy=0;
    fo(i,1,n){
        if (a[i]!=b[i]) break;
        if (a[i]!=2&&a[i]!=3&&a[i]!=5&&a[i]!=7){
            czy=1;
            break;
        }
        y=(y+a[i])%3;
    }
    if (czy){
        printf("%d\n",ans);
        fclose(stdin);fclose(stdout);
        return 0;
    }
    czy=0;
    x=i;
    if (x==1&&b[1]==0) czy=1;
    fo(j,1,4){
        if (pri[j]<b[x]||pri[j]>a[x]) continue;
        if (pri[j]==a[x]) f[x][(y+pri[j])%3][1][0]++;
        else if (pri[j]==b[x]) f[x][(y+pri[j])%3][0][1]++;
        else f[x][(y+pri[j])%3][0][0]++;
    }
    if (czy) f[x][0][0][1]++;
    fo(i,x,n-1){
        if (b[i+1]!=0) czy=0;
        fo(k,0,2){
            if (!f[i][k][0][0]&&!f[i][k][0][1]&&!f[i][k][1][0]) continue;
            fo(j,1,4){
                if (pri[j]==a[i+1])
                    f[i+1][(k+pri[j])%3][1][0]=(f[i+1][(k+pri[j])%3][1][0]+f[i][k][1][0])%mo;
                if (pri[j]==b[i+1])
                    f[i+1][(k+pri[j])%3][0][1]=(f[i+1][(k+pri[j])%3][0][1]+f[i][k][0][1])%mo;
                f[i+1][(k+pri[j])%3][0][0]=(f[i+1][(k+pri[j])%3][0][0]+f[i][k][0][0])%mo;
                if (pri[j]<a[i+1])
                    f[i+1][(k+pri[j])%3][0][0]=(f[i+1][(k+pri[j])%3][0][0]+f[i][k][1][0])%mo;
                if (pri[j]>b[i+1])
                    f[i+1][(k+pri[j])%3][0][0]=(f[i+1][(k+pri[j])%3][0][0]+f[i][k][0][1])%mo;
            }
        }
        if (czy) f[i+1][0][0][1]++;
    }
    ans=((ans-f[n][z][0][0]-f[n][z][0][1]-f[n][z][1][0])%mo+mo)%mo;
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值