HDU 3652
和上题类似,但加上了一个条件要被13整除。可以想到要设三维。开始时设DP[I][J][K],直接设能否被13整除为一类,但转移不了。。。
可以设DP[I][J][K]令J为除13后的余数,I为位数,K代表位数中13的情况,这样转移就方便了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 7 using namespace std; 8 int dp[14][13][3]; 9 int md[13],a[13]; 10 int n; 11 void initial(){ 12 memset(md,0,sizeof(md)); 13 md[1]=1; 14 for(int i=2;i<13;i++){ 15 md[i]=(md[i-1]*10)%13; 16 } 17 memset(dp,0,sizeof(dp)); 18 dp[0][0][0]=1; 19 for(int i=1;i<14;i++){ 20 for(int j=0;j<13;j++){ 21 for(int k=0;k<10;k++){ 22 dp[i][(k*md[i]+j)%13][0]+=dp[i-1][j][0]; 23 } 24 dp[i][(md[i]+j)%13][0]-=dp[i-1][j][1]; 25 dp[i][(j+md[i]*3)%13][1]+=dp[i-1][j][0]; 26 dp[i][(md[i]+j)%13][2]+=dp[i-1][j][1]; 27 for(int k=0;k<10;k++){ 28 dp[i][(k*md[i]+j)%13][2]+=dp[i-1][j][2]; 29 } 30 } 31 } 32 } 33 34 int slove(){ 35 n++; 36 int tmp=n; 37 int len=0; 38 while(tmp){ 39 a[++len]=tmp%10; 40 tmp/=10; 41 } 42 a[len+1]=0; 43 int ans=0,mod=0; 44 bool flag=false; 45 for(int i=len;i>0;i--){ 46 for(int k=0;k<a[i];k++){ 47 ans+=dp[i-1][((0-md[i]*k-mod)%13+13)%13][2]; 48 } 49 if(flag){ 50 for(int k=0;k<a[i];k++){ 51 ans+=(dp[i-1][((0-md[i]*k-mod)%13+13)%13][0]); 52 } 53 } 54 if(!flag&&a[i]>1){ 55 ans+=(dp[i-1][((0-md[i]-mod)%13+13)%13][1]); 56 } 57 if(!flag&&a[i+1]==1&&a[i]>3){ 58 ans+=dp[i][((0-mod)%13+13)%13][1]; 59 } 60 if(a[i+1]==1&&a[i]==3){ 61 flag=true; 62 } 63 mod=(mod+a[i]*md[i])%13; 64 } 65 return ans; 66 } 67 68 int main(){ 69 initial(); 70 while(scanf("%d",&n)!=EOF){ 71 printf("%d\n",slove()); 72 } 73 return 0; 74 }