表示数位dp方面基本是一窍不通,特此选了几个基础题练练,先贴代码,思路有时间再补。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int dp[15][11][13][2];
int pow(int a,int b)
{
int ret = 1;
while(b)
{
ret*=a;
b--;
}
return ret;
}
void init()
{
memset(dp,0,sizeof(dp));
for(int j = 0; j<=9; j++)
{
dp[1][j][j][0] = 1;
}
for(int i = 2; i<=10; i++)
{
for(int j = 0; j<=9; j++)
{
for(int k = 0; k<=12; k++)
{
for(int jj = 0; jj<=9; jj++)
{
if(j == 1&&jj == 3)continue;
dp[i][j][k][0]+=dp[i-1][jj][(k-(j*pow(10,i-1))%13+13)%13][0];
}
for(int jj = 0; jj<=9; jj++)
{
if(j == 1&&jj == 3)dp[i][j][k][1]+=dp[i-1][jj][(k-(j*pow(10,i-1))%13+13)%13][0];
dp[i][j][k][1]+=dp[i-1][jj][(k-(j*pow(10,i-1))%13+13)%13][1];
}
}
}
}
}
int cal(int n)
{
int l = 0;
int bit[11];
int tmp = n;
while(n)
{
bit[++l] = n%10;
n/=10;
}
bit[l+1] = 0;
int ret = 0;
for(int i = 1; i<l; i++)
{
for(int j = 1; j<=9; j++)
{
ret+=dp[i][j][0][1];
}
}
for(int j = 1; j<bit[l]; j++)
{
ret+=dp[l][j][0][1];
}
bool flag = false;
int mod = bit[l]*pow(10,l-1)%13;;
for(int i = l-1; i>0; i--)
{
if(!flag)
for(int j = 0; j<bit[i]; j++)
{
ret+=dp[i][j][(0-mod+13)%13][1];
}
if(flag)
{
for(int j = 0; j<bit[i]; j++)
{
ret+=dp[i][j][(0-mod+13)%13][0]+dp[i][j][(0-mod+13)%13][1];
}
}
if((bit[i+1] == 1&&bit[i]>3)&&!flag)
{
ret+=dp[i][3][(0-mod+13)%13][0];
}
if(bit[i+1] == 1&&bit[i] == 3)
{
flag = true;
}
mod = (mod+bit[i]*pow(10,i-1)%13)%13;
}
return ret;
}
int main()
{
int n;
init();
while(scanf("%d",&n)!=EOF)
{
printf("%d\n",cal(n+1));
}
return 0;
}