来源:HDU3652
数位dp
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[15][13][3];
int n;
int mod[15];
//dp[n][mod][st] represents we have a n-number which mod 13==mod
//and the st means teh same thing that the highest is 1 or 3 or other
void ini(){
memset(mod,0,sizeof(mod));
memset(dp,0,sizeof(dp));
mod[1]=1;
for(int i=2;i<10;i++){
mod[i]=(mod[i-1]*10)%13;
}
dp[0][0][0]=1;
for(int i=0;i<10;i++){
dp[1][i][0]=1;
}
dp[1][3][1]=1;
for(int i=1;i<9;i++){
for(int j=0;j<13;j++){
for(int k=0;k<=9;k++){
int du=(j+k*mod[i+1])%13;
dp[i+1][du][0]+=dp[i][j][0];
dp[i+1][du][2]+=dp[i][j][2];
if(k==3){
dp[i+1][du][1]+=dp[i][j][0];
}
if(k==1){
dp[i+1][du][0]-=dp[i][j][1];
dp[i+1][du][2]+=dp[i][j][1];
}
}
}
}
}
int dpfun(int n){
int shu[15];
memset(shu,0,sizeof(shu));
int len=0;
int ans=0;
bool flag;
flag=false;
int pre=0;
while(n){
shu[++len]=n%10;
n/=10;
}
//shu[len]=0;
/*for(int i=0;i<=len;i++)
cout<<shu[i]<<" ";
cout<<endl;*/
for(int i=len;i>=1;--i){
for(int j=0;j<shu[i];++j){
int temp=(13-(pre*10+j)*mod[i]%13)%13;
ans+=dp[i-1][temp][2];
if(flag||j==3&&pre%10==1)
ans+=dp[i-1][temp][0];
else if(j==1)
ans+=dp[i-1][temp][1];
}
pre=(pre*10)+shu[i];
if(i!=len&&shu[i+1]==1&&shu[i]==3) flag=true;
}
return ans;
}
int main(){
ini();
while(scanf("%d",&n)!=EOF){
cout<<dpfun(n+1)<<endl;
}
return 0;
}