Codeforces Round #235 (Div. 2) D Roman and Numbers(状态DP)
来源:互联网 发布:中昌数据最新消息 编辑:程序博客网 时间:2024/05/09 05:45
Roman is a young mathematician, very famous in Uzhland. Unfortunately, Sereja doesn't think so. To make Sereja change his mind, Roman is ready to solve any mathematical problem. After some thought, Sereja asked Roma to find, how many numbers are close to number n, modulo m.
Number x is considered close to number n modulo m, if:
- it can be obtained by rearranging the digits of number n,
- it doesn't have any leading zeroes,
- the remainder after dividing number x by m equals 0.
Roman is a good mathematician, but the number of such numbers is too huge for him. So he asks you to help him.
Input
The first line contains two integers: n (1 ≤ n < 1018) and m (1 ≤ m ≤ 100).
Output
In a single line print a single integer — the number of numbers close to number n modulo m.
- 数位DP,用dp[mask][m]记录余数为m的个数,mask标记使用了哪些位。
- mask相当于做了一个hash。
eg: 数1234
1 -> 1
10 -> 2
11 -> 21 、 21
100 ->3
101 ->31 、13
110 ->32 、23
111 ->321 、 312 、 213 , 231 , 123 ,132 也就是相应位置3个数的组合
1000 ->4
1001 ->41 ,14 也就是相应2个数位的组合
111 这个状态3个数字都出现; 可以有“32” +“1” , “31” +“2”,......
就是由2个数字尾巴加1个数字转移得来。也就是说从下往上跟新状态。
- 避免0开头,将非0的单个数字的对应为赋值为1。
- 将数字从大到小排序,每次添加一个状态相当于在任意数字组合的末尾添加一个数字,dp[mask & (1 << i)][(m * 10 + digit[i]) % m] += dp[mask][m]。
- 结果为dp[(1 << digitNum) - 1][0]除以排列数。
typedef long long LL ;LL dp[1<<18][101] ;LL num[18] ;LL repeat_dig[10] ;LL fac[19] ;LL DP(string str , int Mod){ int i , j , n , k ; LL repeat = 1 ; memset(repeat_dig , 0 , sizeof(repeat_dig)) ; memset(dp , 0 , sizeof(dp)) ; n = str.length() ; for(i = 0 ; i < n ; i++){ num[i] = str[i] - '0' ; repeat_dig[num[i]]++ ; } for(i = 0 ; i <= 9 ; i++) repeat *= fac[repeat_dig[i]] ; sort(num , num + n) ; for(i = 0 ; i < n ; i++){ if(num[i] > 0) dp[1<<i][num[i]%Mod] = 1 ; } for(i = 1 ; i < (1<<n) ; i++){ for(j = 0 ; j < Mod ; j++){ if(dp[i][j]){ for(k = 0 ; k < n ; k++){ if((i & (1<<k)) == 0) dp[i|(1<<k)][(j*10 + num[k]) % Mod] += dp[i][j] ; } } } } return dp[(1<<n)-1][0]/repeat ;}int main(){ fac[0] = 1 ; for(int i = 1 ; i <= 18 ; i++) fac[i] = fac[i-1] * i ; string s ; int mod ; while(cin>>s>>mod){ cout<<DP(s, mod)<<endl ; } return 0 ;}
记忆化搜索(好懂):
typedef long long LL ;LL dp[1<<18][101] ;LL num[18] ;LL repeat_dig[10] ;LL fac[19] ;bool visited[1<<18] ;int n , Mod ;void dfs(int state){ if(visited[state]) return ; visited[state] = 1 ; for(int i = 0 ; i < n ; i++){ if((state | (1<<i)) != state) continue ; int now = state - (1<<i) ; if(now == 0) continue ; dfs(now) ; for(int j = 0 ; j < Mod ; j++) dp[state][(j*10 + num[i]) % Mod] += dp[now][j] ; }}LL DP(string str){ int i , j , k ; LL repeat = 1 ; memset(repeat_dig , 0 , sizeof(repeat_dig)) ; memset(dp , 0 , sizeof(dp)) ; memset(visited , 0 , sizeof(visited)) ; n = str.length() ; for(i = 0 ; i < n ; i++){ num[i] = str[i] - '0' ; repeat_dig[num[i]]++ ; } for(i = 0 ; i <= 9 ; i++) repeat *= fac[repeat_dig[i]] ; for(i = 0 ; i < n ; i++){ if(num[i]) dp[1<<i][num[i]%Mod] = 1 ; } dfs((1<<n)-1) ; return dp[(1<<n) -1][0]/repeat ;}int main(){ fac[0] = 1 ; for(int i = 1 ; i <= 18 ; i++) fac[i] = fac[i-1] * i ; string s ; while(cin>>s>>Mod){ cout<<DP(s)<<endl ; } return 0 ;}
0 0
- Codeforces Round #235 (Div. 2) D Roman and Numbers(状态DP)
- Codeforces Round #235 (Div. 2) D. Roman and Numbers (数位dp、状态压缩)
- Codeforces Round #235 (Div. 2) D. Roman and Numbers(状态压缩DP)
- Codeforces Round #235 (Div. 2) D. Roman and Numbers 解题报告(状态压缩)
- Codeforces Round #235 (Div. 2) ----D. Roman and Numbers
- Codeforces Round #235 (Div. 2) D. Roman and Numbers
- Codeforces Round #235 (Div. 2) / 410D Roman and Numbers (带有整除性质的数位DP)
- Codeforces Round #235 (Div. 2) D. Roman and Numbers(状压dp)
- CodeForces 401D Roman and Numbers【数位dp+状态压缩】
- codeforces 401D Roman and Numbers(状态压缩)
- codeforces 401D Roman and Numbers (数位dp)
- codeforces 401D D. Roman and Numbers(状态压缩dp+数论)
- codeforces #235 D. Roman and Numbers 题解
- Codeforces Round #321 (Div. 2) D. Kefa and Dishes 位 状态压缩 dp
- codeforces#235_div2_D Roman and Numbers ,dp
- Codeforce 401D Roman and Numbers[数位DP+状态压缩]
- [数位dp] Codeforces 401D Roman and Numbers
- Codeforces 401D Roman and Numbers【状压dp】
- cocos2dx创建android独立工程及eclipse编译
- 在ORACLE中获取表名和列名
- XMPP即时通讯资料记录
- NoSQL架构实践
- DICOM和BMP的转换问题
- Codeforces Round #235 (Div. 2) D Roman and Numbers(状态DP)
- java xml 学习(三)
- 不建议使用类型 Activity 的方法 managedQuery(Uri, String[], String, String[], String)解决方案
- PAT 1051. Pop Sequence (25)
- web.xml配置详解
- Unity3D_场景の烘培
- Glassfish初探
- 菜鸟是如何写一个过滤器Filter 的
- oracle 8 statspack安装配置