Painful Bases
这个题目一开始看,感觉有点像数位dp,但是因为是最多有16进制,因为限制了每一个数字都不同最多就有16个数。
所以可以用状压dp,看网上题解是
dp[s][r] 表示数字集合为s,对 k 取余为r的方案数。
这个题目首先把给你的字符转化成数字,然后枚举状态,枚举模数,枚举每一位的所有可能。
这个注意是写离散化的,不是直接暴力,虽然理论上都会超时,但是实际上离散化的没有超时。
这个题目我觉得还挺好的,以后可以在写写
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; typedef long long ll; ll dp[1 << 17][20]; char s[100]; int num[100]; int main() { int t; scanf("%d", &t); for(int cas=1;cas<=t;cas++) { int base, k; scanf("%d%d", &base, &k); scanf("%s", s + 1); int len = strlen(s + 1); for(int i=1;i<=len;i++) { if (s[i] <= '9'&&s[i] >= '0') num[i] = s[i] - '0'; else num[i] = 10 + s[i] - 'A'; } memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for(int i=0;i<(1<<len);i++) { for(int mod=0;mod<k;mod++) { if (dp[i][mod] == 0) continue; for(int id=1;id<=len;id++) { int tmp = (1 << (id-1)); if ((tmp | i) == i) continue; tmp |= i; dp[tmp][(mod*base + num[id]) % k] += dp[i][mod]; } } } printf("Case %d: %lld ", cas,dp[(1 << len) - 1][0]); } return 0; }
排列perm
这个题目和上面的差不多,有一个小地方注意一下,就是这个有相同的所以要除去。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <map> #include <queue> #include <vector> #define sum 1<<10 #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int maxn = 4e5 + 10; ll dp[1 << 10][1000]; int a[maxn]; int vis[10]; char s[maxn]; int main() { int t; scanf("%d", &t); while (t--) { int d; scanf("%s%d", s + 1, &d); memset(vis, 0, sizeof(vis)); int len = strlen(s + 1); int tmp = 0; for (int i = 1; i <= len; i++) { a[i] = s[i] - '0'; tmp |= (1 << a[i]); vis[a[i]]++; } ll ans = 1; for(int i=0;i<=9;i++) { if(vis[i]) { for(int j=1;j<=vis[i];j++) { ans *= j; } } } memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for (int i = 0; i < (1 << len); i++) { for (int mod = 0; mod < d; mod++) { if (dp[i][mod] == 0) continue; for (int j = 1; j <= len; j++) { int tmp1 = (1 << (j - 1)); if ((tmp1 | i) == i) continue; tmp1 |= i; dp[tmp1][(mod * 10 + a[j]) % d] += dp[i][mod]; } } } printf("%lld ", dp[(1<<len)-1][0]/ans); } return 0; }