题意:将一个数划分成两部分,如果过分出来的两部分相加能被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 ",solve(r+1,k)-solve(l,k)); 96 } 97 return 0; 98 }