这道题大牛们都说水题,可是我刚开始做数位dp,感觉好吃力啊!
网上大部分都是用dfs写的,可惜我一开始和大家的入门思路就不一样,我一直习惯用递推。哎,感觉姿势不对啊。
递推预处理的复杂度更高一点。不过我觉得符合我的思维方式。没办法,改不了。
我就不说什么了,不要受我的思维影响,还是要学会大部分的思维方式才是正确的选择。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,ans;
__int64 bit[13];
int digit[13];
int dp[15][11][3][15];
void init()
{
memset(dp,0,sizeof(dp));
int i,j,k,m,x;
bit[0]=1;
for(i=1;i<=12;i++) bit[i]=bit[i-1]*10;
dp[0][0][0][0]=1;
for(i=1;i<=10;i++)
{
for(j=0;j<=9;j++)
{
for(m=0;m<=12;m++)
{
for(x=0;x<=9;x++)
for(k=0;k<=1;k++)
if(k==1)
{
dp[i][j][k][m]+=dp[i-1][x][1][(m-(j*bit[i-1]%13)+13)%13];
if(j==1&&x==3)
dp[i][j][k][m]+=dp[i-1][x][0][(m-(j*bit[i-1]%13)+13)%13];
//cout<<dp[i][j][k][m]<<endl;
}
else
{
if(!(j==1&&x==3))
{
dp[i][j][k][m]+=dp[i-1][x][0][(m-(j*bit[i-1]%13)+13)%13];
}
}
}
}
}
}
void work(int num)
{
int i,j,k,m,x;
int len=0;
memset(digit,0,sizeof(digit));
while(num)
{
digit[++len]=num%10;
num/=10;
}
digit[len+1]=0;
ans=0;
int flag=0,mod=0;
for(i=len;i;i--)
{
for(j=0;j<digit[i];j++)
{
ans+=dp[i][j][1][(13-(mod*bit[i]%13))%13];
if(flag||j==3&&digit[i+1]==1)
ans+=dp[i][j][0][(13-(mod*bit[i]%13))%13];
}
if(digit[i]==3&&digit[i+1]==1) flag=1;
mod=(mod*10+digit[i])%13;
}
printf("%d\n",ans);
}
int main()
{
int i,j;
int k,m;
init();
while(scanf("%d",&n)!=EOF)
{
work(n+1);
}
return 0;
}