题意:将一个数划分成两部分,如果过分出来的两部分相加能被k整除,则这种划分时可行的,题目要我们求的是一段区间内的数有多少种可行的划分方法(PS:一个数可以有多种划分方法,如333 3有两种分别是33|3 , 3|33)

http://acm.hdu.edu.cn/showproblem.php?pid

dp[i][j][k][l]表示处理到第i位,划分位置为j,除数为k,余数为l的,划分方法数。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 #define ll __int64
 6 ll dp[18][18][22][22],md[19]={0,1};
 7 void init()
 8 {
 9     for(int i=2;i<19;i++)
10     md[i]=10*md[i-1];
11     memset(dp,0,sizeof(dp));
12     for(int k=1;k<21;k++)
13         for(int l=0;l<k;l++)
14             for(int j=0;j<10;j++)
15                 if(j%k==l)
16                     dp[1][1][k][l]++;
17     for(int i=2;i<18;i++){
18         for(int j=1;j<=i;j++){
19             for(int k=1;k<21;k++){
20                 for(int l=0;l<k;l++){
21                     for(int j1=0;j1<10;j1++){
22                         if(i!=j){
23                             ll tmp=(j1*md[i-j])%k;
24                             dp[i][j][k][l]+=dp[i-1][j][k][(l+k-tmp)%k];
25                         }
26                         else{
27                             ll tmp=(j1*md[i])%k;
28                             dp[i][i][k][l]+=dp[i-1][i-1][k][(l+k-tmp)%k];
29                         }
30                     }
31                 }
32             }
33         }
34     }
35 }
36 ll solve(ll x,ll k)
37 {
38     ll dig[20],cnt=0,ans=0,tx=x;
39     while(x){
40         dig[++cnt]=x%10;
41         x/=10;
42     }
43     if(cnt>2){
44         for(int i=1;i<cnt-1;i++)
45         ans+=dp[cnt-1][i][k][0];
46         for(int i=cnt-2;i>0;i--)
47         ans-=dp[i][i][k][0];
48     }
49     
50     for(int i=1;i<dig[cnt];i++){
51         for(int j=1;j<cnt;j++){
52             ll tmp=(i*md[cnt-j])%k;
53             ans+=dp[cnt-1][j][k][(k-tmp)%k];
54         }
55         
56     }
57     for(int i=cnt-1;i>1;i--){
58         for(int j=0;j<dig[i];j++){
59             ll cntt=cnt-1,tmp2=0,tmp1=dig[cnt];
60             while(cntt>i){
61                 tmp2=10*tmp2+dig[cntt];
62                 cntt--;
63             }
64             for(int kk=cnt-1;kk>=i;kk--){
65                 ll tmp3=(tmp1)%k;
66                 ll tmp4=(tmp2*md[i+1])%k;
67                 ll tmp5=(j*md[i])%k;
68                 ans+=dp[i-1][i-1][k][(k-tmp3-tmp4-tmp5+2*k)%k];
69                 tmp1=tmp1*10+dig[kk];
70                 tmp2=tmp2-dig[kk]*md[kk-i];
71             }
72             tmp1=tmp1-dig[i]+j;
73             for(int kk=i-1;kk>0;kk--){
74                 ll tmp3=(tmp1*md[i-kk])%k;
75                 ans+=dp[i-1][kk][k][(k-tmp3)%k];
76             }
77         }
78     }
79     for(int i=0;i<dig[1];i++){
80         ll su1=tx-dig[cnt]*md[cnt]-tx%10,su2=tx/md[cnt];
81         for(int j=cnt-1;j>0;j--){
82             if((su1+su2+i)%k==0)
83                 ans++;
84             su2=10*su2+dig[j];
85             su1=su1-dig[j]*md[j];
86         }
87     }
88     return ans;
89 }
90 int main()
91 {
92     init();
93     ll l,r,k,cnt=1;
94     while(~scanf("%I64d%I64d%I64d",&l,&r,&k)){
95         printf("%I64d\n",solve(r+1,k)-solve(l,k));
96     }
97     return 0;
98 }
AC Code