Qiuqiqiu  
不管道路多么崎岖坎坷,我永远不停下追逐梦想的脚步!

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 }

 

posted on 2012-11-16 21:53  Qiuqiqiu  阅读(1415)  评论(0编辑  收藏  举报