这道题参考了百度文库中的课件http://wenku.baidu.com/link?url=zZWAUhUwQPzg1s6s4N1AAi-hv3hHaVf83-Wxp4zCWGBeerEHOddF1V1miCLNrZnVvARM2vTBaWAkKqgZXx26h8SHw82-rB7wxa3rDSskZjW
题意是找到从1到n中间包含“13”以及可以被13整除的数字的个数。
dfs(len,j,k,l,flag)表示长度为len,j为第len +1位的数字是,k为是否包含13,l为膜13以后的余数,flag标记是否能够取到9。
决策第i位:
for x = 0 ~ 9
if k = 1 //要求要包含13
f[i,j,k,l] = f[i - 1,x,1,m];
if j = 1 and x = 3 //已经有13了。
f[i,j,k,l] = f[i,j,k,l] +
f[i - 1,x,0,m];
else //不要求包含13
if not (j = 1 and x = 3)
f[i,j,k,l] = f[i - 1,x,0,m];
m即方程(10^(len-1)*j+n)%13=l,m=n%13的解。
在求解过程中使用记忆化搜索。
代码如下:
#include<iostream>
#include<cstring>
using namespace std;
int digit[11];
int dp[12][10][2][15];
int pow(int n,int t){
// cout<<"pow"<<n<<' '<<t<<' ';
if(t<=0){
// cout<<0<<endl;
return 0;
}
int tmp=1;
for(int i=0;i<t;++i){
tmp*=n;
}
// cout<<tmp<<endl;
return tmp;
}
int dfs(int len,int j,int k,int l,int flag){
// cout<<"len="<<len<<' '<<"i+1digit"<<j<<' '<<"contain13="<<k<<' '<<"%13="<<l<<' '<<digit[len]<<endl;
if(len==0){
if(k)return 0;
if(l>9)return 0;
if(j!=l)return 0;
return 1;
}
if(flag&&dp[len][j][k][l]!=-1)return dp[len][j][k][l];
int ans=0;
int fmax=flag?9:digit[len];
int tmp;
for(int i=0;i<=13;++i){
if((pow(10,len)*j+i)%13==l){tmp=i;break;}
}
// cout<<len-1<<' '<<pow(10,len-1)*j<<' '<<"tmp="<<tmp<<endl;
for(int i=0;i<=fmax;++i){
if(k==1){
ans+=dfs(len-1,i,k,tmp,flag||i<fmax);
if(j==1&&i==3){
ans+=dfs(len-1,i,0,tmp,flag||i<fmax);
}
}
else {
if(j==1&&i==3)continue;
ans+=dfs(len-1,i,0,tmp,flag||i<fmax);
}
}
if(flag){
dp[len][j][k][l]=ans;
}
return ans;
}
int solve(int n){
int len=0;
while(n){
digit[++len]=n%10;
n/=10;
}
return dfs(len,0,1,0,false);
}
int main(){
// freopen("data.txt","r",stdin);
int n;
memset(dp,-1,sizeof(dp));
while(cin>>n){
cout<<solve(n)<<endl;
}
return 0;
}
在第一次提交是,将dfs函数的第四个参数的含义弄错了,传参数就不对。(第一次理解成(10^(len-1)+l)%13=tmp)
改正后,提交仍然错误,原因是前面写的时候先把dfs的第二个参数定义为是否第len+1位为1,后来更正成为表示len+1位的值,然后在for循环中的else里面忘记把if(j&&i==3)continue;改成if(j==1&&i==3)continue,然后在1339的时候判断开始出错。
刚开始接触数位DP,上个星期三看了第一道数位DP,用了三天时间写出来(因为有好多课,还看了别人的题解以后参考的写的),这道题只看了一个课件的思路,写程序的时候完全没有看别人的代码,在写完以后第二个错误找不到了然后开始运行别人的代码,找到了错误的数据,想了七八个小时吧……