hdu3652 数位dp
dp[i][j][k] i-i位数,j-开头是j,k-除13的余数
要注意数位dp的时候一定不能直接判断对的来做,必须是判断不对的,然后用全部减
这一题先算出所有%13==0的个数,然后算出所以%13并且不含13的个数,然后相减就是答案了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 2520 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const double g=10.0,eps=1e-7; const int N=10+10,maxn=1000000+10,inf=0x3f3f3f; int dp1[N][10][20],dp2[N][10][20],digit[N]; int dfs1(int len,int before,int left,bool fp) { if(!len)return left==0; if(!fp&&dp1[len][before][left]!=-1)return dp1[len][before][left]; int ans=0,fpmax=fp ? digit[len] : 9; for(int i=0;i<=fpmax;i++) { if(i==3&&before==1)continue; ans+=dfs1(len-1,i,(left*10+i)%13,fp&&i==fpmax); } if(!fp)dp1[len][before][left]=ans; return ans; } int dfs2(int len,int before,int left,bool fp) { if(!len)return left==0; if(!fp&&dp2[len][before][left]!=-1)return dp2[len][before][left]; int ans=0,fpmax=fp ? digit[len] : 9; for(int i=0;i<=fpmax;i++) { ans+=dfs2(len-1,i,(left*10+i)%13,fp&&i==fpmax); } if(!fp)dp2[len][before][left]=ans; return ans; } int solve(int x) { int len=0; while(x) { digit[++len]=x%10; x/=10; } return dfs2(len,0,0,1)-dfs1(len,0,0,1); } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; memset(dp1,-1,sizeof dp1); memset(dp2,-1,sizeof dp2); while(cin>>n)cout<<solve(n)<<endl; return 0; } /******************** dp[i][j][k] i-i位数,j-开头是j,k-除13的余数 ********************/