HDU 4669 Mutiples on a circle(环状DP)

题目链接

这是最早看懂题意的一题,状态转移,挺好想。。但是比赛时候,就是没有想到怎么去重,而且当时有些情况,也没注意到。

先预处理的dp[0]的情况,就是以p[0]为结尾的情况。之后D就行了,例如样例此位6,去重只要把642896 去掉就行了,dp[1][642896%m] --;注意这个值的更新。

突然发现。

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define LL __int64
 5 int dp[50100][201];
 6 int p[50100];
 7 int d[50100];
 8 int po[200100];
 9 int fun(int x)
10 {
11     int i = 0;
12     while(x)
13     {
14         i ++;
15         x = x/10;
16     }
17     return i;
18 }
19 int main()
20 {
21     int n,m,i,j,sum,pre;
22     while(scanf("%d%d",&n,&m)!=EOF)
23     {
24         for(i = 0;i <= n;i ++)
25         {
26             for(j = 0;j < m;j ++)
27             dp[i][j] = 0;
28         }
29         po[0] = 1;
30         for(i = 1;i <= 4*n;i ++)
31         {
32             po[i] = (po[i-1]*10)%m;
33         }
34         for(i = 0;i < n;i ++)
35         {
36             scanf("%d",&p[i]);
37             d[i] = fun(p[i]);
38         }
39         p[n] = p[0];
40         d[n] = d[0];
41         sum = 0;
42         pre = 0;
43         for(i = n;i > 0;i --)
44         {
45             sum = (p[i]*po[pre] + sum)%m;
46             pre += d[i];
47             dp[0][sum] ++;
48         }
49         for(i = 1;i < n;i ++)
50         {
51             for(j = 0;j < m;j ++)
52             {
53                 dp[i][(j*po[d[i]]+p[i])%m] += dp[i-1][j];
54             }
55             sum = (sum*po[d[i]] + p[i])%m;
56             dp[i][sum] --;
57             dp[i][p[i]%m] ++;
58             sum = (sum - po[pre]*p[i])%m;
59             if(sum < 0)
60             sum += m;
61         }
62         LL ans = 0;
63         for(i = 0;i < n;i ++)
64         {
65             ans += dp[i][0];
66         }
67         printf("%I64d
",ans);
68     }
69     return 0;
70 }
原文地址:https://www.cnblogs.com/naix-x/p/3257358.html