http://acm.hdu.edu.cn/showproblem.php?pid=3652
题意:求小于n是13的倍数且含有'13'的数的个数
dp[i][j][k]
i:第i位,j:余数为j
k=0:不含13 1:3开头不含13 2:含13
View Code
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 const int N=12; 6 int md[N]; 7 int dp[N][13][3]; 8 void getdp() 9 { 10 md[0]=1; 11 for(int i=1;i<N;i++) md[i]=md[i-1]*10%13; 12 memset(dp,0,sizeof(dp)); 13 dp[0][0][0]=1; 14 for(int i=0;i<N-1;i++) 15 for(int j=0;j<13;j++) 16 { 17 for(int k=0;k<10;k++) 18 dp[i+1][(j+md[i]*k)%13][0]+=dp[i][j][0]; 19 dp[i+1][(j+md[i])%13][0]-=dp[i][j][1]; 20 dp[i+1][(j+md[i]*3)%13][1]+=dp[i][j][0]; 21 dp[i+1][(j+md[i])%13][2]+=dp[i][j][1]; 22 for(int k=0;k<10;k++) 23 dp[i+1][(j+md[i]*k)%13][2]+=dp[i][j][2]; 24 } 25 } 26 int getans(int n) 27 { 28 int d[11],len=0; 29 for(int i=n;i;i/=10) d[len++]=i%10; 30 d[len]=0; 31 bool flag=false; 32 int ans=0,mod=0; 33 for(int i=len-1;i>=0;mod=(mod+d[i]*md[i])%13,i--) 34 { 35 for(int j=0;j<d[i];j++) ans+=dp[i][(13-(mod+j*md[i])%13)%13][2]; 36 if(flag) 37 { 38 for(int j=0;j<d[i];j++) ans+=dp[i][(13-(mod+j*md[i])%13)%13][0]; 39 continue; 40 } 41 if(d[i+1]==1 && d[i]>3) ans+=dp[i+1][(13-mod)%13][1]; 42 if(d[i]>1) ans+=dp[i][(13-(mod+md[i])%13)%13][1]; 43 if(d[i+1]==1 && d[i]==3) flag=true; 44 } 45 return ans; 46 } 47 int main() 48 { 49 getdp(); 50 int n; 51 while(~scanf("%d",&n)) 52 { 53 int ans=getans(n+1); 54 printf("%d\n",ans); 55 } 56 return 0; 57 }