码迷,mamicode.com
首页 > 其他好文 > 详细

【Foreign】Number [状压DP]

时间:2017-09-16 22:04:37      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:while   表示   mem   判断   string   eve   splay   click   log   

Number

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

  技术分享

Input

  技术分享

Output

  技术分享

Sample Input

  12345 5

Sample Output

  24

HINT

  技术分享

Solution

  我们运用状压DP令 f[j][opt] 表示当前余数为 j,状态为opt的方案

  状态记录的是:各个数字被用了几次。

  那么我们就可以状压了。先DFS出每个状态,记sum[k]表示后缀积,那么显然 从 opt 转移到 第k个数字多用一次的状态 就是 opt + sum[k + 1]

  注意判断一下首位不能为0

Code

技术分享
 1 #include<iostream>    
 2 #include<string>    
 3 #include<algorithm>    
 4 #include<cstdio>    
 5 #include<cstring>    
 6 #include<cstdlib>
 7 #include<cmath>
 8 #include<vector>
 9 #include<queue>
10 using namespace std;  
11 typedef long long s64;
12 
13 const int ONE = 500005;
14 const int MOD = 998244353;
15 
16 int n, m;
17 int num;
18 int vis[ONE], Num[20], sum[20];
19 int f[105][200005];
20 int Sta[ONE][10];
21 char ch[ONE];
22 
23 int get()
24 {
25         int res=1,Q=1;char c;
26         while( (c=getchar())<48 || c>57 ) 
27         if(c==-)Q=-1; 
28         res=c-48;     
29         while( (c=getchar())>=48 && c<=57 )
30         res=res*10+c-48;    
31         return res*Q;
32 }
33 
34 void Dfs(int T)
35 {
36         if(T > 10)
37         {
38             num++;
39             for(int i = 0; i <= 9; i++)
40                 Sta[num][i] = vis[i];
41             return;
42         }
43         
44         for(int i = 0; i <= Num[T]; i++)
45             vis[T] = i, Dfs(T + 1);
46 }
47 
48 int main()
49 {
50         scanf("%s", ch + 1);    m = get();
51         n = strlen(ch + 1);
52         
53         for(int i = 1; i <= n; i++) Num[ch[i] - 0]++;
54         sum[10] = 1; for(int i = 9; i >= 0; i--) sum[i] = sum[i + 1] * (Num[i] + 1);
55         
56         Dfs(0);
57         
58         f[0][1] = 1;
59         for(int opt = 1; opt <= num; opt++)
60             for(int j = 0; j < m; j++)
61                 if(f[j][opt])
62                     for(int k = 0; k <= 9; k++)
63                     {
64                         if(opt == 1 && k == 0) continue;
65                         if(Sta[opt][k] >= Num[k]) continue; 
66                         int to = opt + sum[k + 1];
67                         f[(j * 10 + k) % m][to] += f[j][opt];
68                         f[(j * 10 + k) % m][to] %= MOD;
69                     }
70         
71         printf("%d", f[0][num]);
72 }
View Code

 

【Foreign】Number [状压DP]

标签:while   表示   mem   判断   string   eve   splay   click   log   

原文地址:http://www.cnblogs.com/BearChild/p/7532820.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!