bzoj 1072: [SCOI2007]排列perm(状压dp)
2017-06-28 02:24
344 查看
1072: [SCOI2007]排列perm
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2272 Solved: 1432
[Submit][Status][Discuss]
Description
给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0)。例如123434有90种排列能被2整除,其中末位为2的有30种,末位为4的有60种。Input
输入第一行是一个整数T,表示测试数据的个数,以下每行一组s和d,中间用空格隔开。s保证只包含数字0, 1, 2, 3, 4, 5, 6, 7, 8, 9.Output
每个数据仅一行,表示能被d整除的排列的个数。Sample Input
7000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29
Sample Output
13
3628800
90
3
6
1398
n这么小,直接状压dp
dp[i][j]表示状态为i( i的二进制表示当前已经使用了串中的某些对应二进制位=1的数),对d取模为j有多少情况
最后答案就是dp[(1<<n)-1][0]
转移:dp[i|(1<<k)][(j*10+a[k+1])%d] += dp[i][j]; (i&(1<<k)==0)
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; char str[15]; int a[15], cnt[15], dp[1055][1055]; int main(void) { int d, T, i, j, k, n, ans; scanf("%d", &T); while(T--) { memset(cnt, 0, sizeof(cnt)); memset(dp, 0, sizeof(dp)); scanf("%s%d", str+1, &d); n = strlen(str+1); for(i=1;i<=n;i++) { a[i] = str[i]-'0'; cnt[a[i]]++; } dp[0][0] = 1; for(i=0;i<(1<<n);i++) { for(j=0;j<d;j++) { for(k=0;k<n;k++) { if(i&(1<<k)) continue; dp[i|(1<<k)][(j*10+a[k+1])%d] += dp[i][j]; } } } ans = dp[(1<<n)-1][0]; for(i=0;i<=9;i++) { for(j=1;j<=cnt[i];j++) ans /= j; } printf("%d\n", ans); } return 0; }
相关文章推荐
- bzoj 1072: [SCOI2007]排列perm 状压dp
- BZOJ 1072 [SCOI2007]排列perm 状压DP
- bzoj1072 [SCOI2007]排列perm(状压dp)
- BZOJ 1072 [SCOI 2007] 排列perm (状压DP)
- BZOJ 1072: [SCOI2007]排列perm [DP 状压 排列组合]
- [SCOI2007] BZOJ 1072 排列perm - 状压dp
- BZOJ 1072 [SCOI2007]排列perm ——状压DP
- BZOJ1072: [SCOI2007]排列perm 状压DP
- [BZOJ1072]-[SCOI2007]排列perm-状压DP
- bzoj 1072: [SCOI2007]排列perm(状压DP)
- [BZOJ1072][SCOI2007]排列perm(状压DP)
- [BZOJ1072][SCOI2007]排列perm(状压dp)
- BZOJ 1072 SCOI2007 排列perm 状压DP
- [BZOJ1072][SCOI2007]排列perm(状压dp)
- [BZOJ1072] [SCOI2007] 排列perm - dfs/dp
- bzoj1072: [SCOI2007]排列perm 压状dp
- 1072: [SCOI2007]排列perm 状压DP
- BZOJ 1072: [SCOI2007]排列perm 状态压缩DP
- BZOJ 1072 [SCOI2007]排列perm (状态压缩+dp+同余定理)
- BZOJ 1072 排列perm (状压dp)