JZOJ 5266. number

来源:互联网 发布:telnet 的端口号是什么 编辑:程序博客网 时间:2024/06/06 00:00

Description

找出1~n范围内含有13并且能被13整除的数字的个数。

Input

第一行一个n。

Output

一个整数表示满足要求的数字个数。

Sample Input

13

Sample Output

1

Data Constraint

对于30%数据n<=100000
对于100%数据n<=10^18

Solution

  • 这是关于数字的问题,典型数位DP。

  • F[i][j][k][l] 表示填到第 i 位、余数为 j 、情况为 k、限制01为 l 的方案数。

  • 其中 k 的取值为 0122 表示已经出现 131 表示这一位填了 10 表示其他情况。

  • 初值为 F[0][0][0][1]=1 ,转移显然。

Code

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int roll;long long n;int a[20];long long f[2][13][3][2];inline int read(){    int X=0,w=1; char ch=0;    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();    return X*w;}int main(){    for(scanf("%lld",&n);n;n/=10) a[++a[0]]=n%10;    reverse(a+1,a+1+a[0]);    f[0][0][0][1]=1;    for(int i=0;i<a[0];i++)    {        for(int j=0;j<13;j++)            for(int k=0;k<2;k++)                if(k)                {                    if(a[i+1]>3) f[roll^1][(j*10+3)%13][2][0]+=f[roll][j][1][1];                    for(int l=0;l<a[i+1];l++)                    {                        f[roll^1][(j*10+l)%13][l==1][0]+=f[roll][j][0][1]+(l!=3)*f[roll][j][1][1];                        f[roll^1][(j*10+l)%13][2][0]+=f[roll][j][2][1];                    }                    f[roll^1][(j*10+a[i+1])%13][a[i+1]==1][1]+=f[roll][j][0][1]+(a[i+1]!=3)*f[roll][j][1][1];                    f[roll^1][(j*10+a[i+1])%13][2][1]+=f[roll][j][2][1];                    if(a[i+1]==3) f[roll^1][(j*10+a[i+1])%13][2][1]+=f[roll][j][1][1];                }else                {                    f[roll^1][(j*10+3)%13][2][0]+=f[roll][j][1][0];                    for(int l=0;l<=9;l++)                    {                        f[roll^1][(j*10+l)%13][l==1][0]+=f[roll][j][0][0]+(l!=3)*f[roll][j][1][0];                        f[roll^1][(j*10+l)%13][2][0]+=f[roll][j][2][0];                    }                }        roll^=1;        memset(f[roll^1],0,sizeof(f[roll^1]));    }    printf("%lld",f[roll][0][2][0]+f[roll][0][2][1]);    return 0;}