Lightoj 1021 Painful Bases (狀壓dp 有趣)
Time Limit: 2 second(s) | Memory Limit: 32 MB |
As you know that sometimes base conversion is a painful task. But still there are interesting facts in bases.
For convenience let's assume that we are dealing with the bases from 2 to 16. The valid symbols are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E and F. And you can assume that all the numbers given in this problem are valid. For example 67AB is not a valid number of base 11, since the allowed digits for base 11 are 0 to A.
Now in this problem you are given a base, an integer K and a valid number in the base which contains distinct digits. You have to find the number of permutations of the given number which are divisible by K. K is given in decimal.
For this problem, you can assume that numbers with leading zeroes are allowed. So, 096 is a valid integer.
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case starts with a blank line. After that there will be two integers, base (2 ≤ base ≤ 16) and K (1 ≤ K ≤ 20). The next line contains a valid integer in that base which contains distinct digits, that means in that number no digit occurs more than once.
Output
For each case, print the case number and the desired result.
Sample Input |
Output for Sample Input |
3
2 2 10
10 2 5681
16 1 ABCDEF0123456789 |
Case 1: 1 Case 2: 12 Case 3: 20922789888000 |
題目連結:http://lightoj.com/volume_showproblem.php?problem=1021
題目大意:base表示base進位制,給一個k(0 <= k <= 20),給一個base進位制下的合法數,保證每位數字都不同,求這個數字的所有排列中是k的倍數的個數
題目分析:因為數字都不同,所以最多隻有16位,因此可以狀壓做,dp[i][j]表示選數狀態為i,模k為j的排列數個數,然後對一個合法狀態擴充套件就是在前面加數字,取模的時候因為((x * base) + num[idx]) % k == ((x * base) % k + num[idx] % k) % k == (j * base + num[idx] % k ) % k所以轉移方程就是
dp[i | (1 << idx)][(j * base + num[idx] % k) % k] += dp[i][j]
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int const MAX = (1 << 16) + 5;
ll dp[MAX][25];
char s[25];
int num[25];
int main()
{
int T;
scanf("%d", &T);
for(int ca = 1; ca <= T; ca++)
{
int b, k;
scanf("%d %d", &b, &k);
scanf("%s", s);
int len = strlen(s);
memset(dp, 0, sizeof(dp));
for(int i = 0; i < len; i++)
num[i] = s[i] >= 'A' ? (10 + s[i] - 'A') : (s[i] - '0');
dp[0][0] = 1;
for(int i = 0; i < (1 << len); i++)
for(int j = 0; j < k; j++)
if(dp[i][j])
for(int idx = 0; idx < len; idx++)
if(!(i & (1 << idx)))
dp[i | (1 << idx)][(j * b + num[idx] % k) % k] += dp[i][j];
printf("Case %d: %lld\n", ca, dp[(1 << len) - 1][0]);
}
}
相關文章
- 狀壓 dp
- 狀壓DP
- [狀壓dp] 最短Hamilton路徑(模板題+狀壓dp)
- HDU 1074 Doing Homework(狀壓DP)
- 簡易狀態壓縮DP
- 狀壓DP基礎入門
- 合理安排(狀壓dp,包括技巧)
- NOI2001 炮兵陣地(狀壓dp)
- E - Remove Pairs(狀壓dp+博弈論)REMAI
- HDU 5816 Hearthstone(狀態壓縮DP+概率)
- Luogu P1777 幫助 題解 [ 紫 ] [ 線性 dp ] [ 狀壓 dp ]
- hdu--5418Victor and World+狀態壓縮DP
- 分組(狀壓dp+技巧:快速列舉子集)
- Codeforces 11D A Simple Task 題解 [ 藍 ] [ 狀壓 dp ]
- bzoj4145: [AMPPZ2014]The Prices(狀態壓縮+Dp)
- 百練4124:海賊王之偉大航路(狀壓DP)
- 一類哈密頓路徑/迴路為背景的狀壓dp
- CF79D Password (差分+狀壓 dp+最短路/bfs)
- [狀壓dp]leeccode1434:每個人戴不同帽子的方案數(hard)
- 動態規劃——用二進位制表示集合的狀態壓縮DP動態規劃
- ACM-ICPC 2018 南京賽區網路預賽__E AC Challenge【狀態壓縮+DP】ACM
- 1021 Deepest Root(甲級)
- 狀態壓縮
- 互不侵犯 (狀壓)
- usering mongotemplate bases on spring-Data-mongoGoSpring
- LightOJ 1038 Race to 1 Again (簡單期望)AI
- 1021. 個位數統計 (15)
- 【PAT乙級】1021 個位數統計
- dp 套 dp(dp of dp)小記
- Luogu P5005 中國象棋 - 擺上馬 / Luogu P8756 國際象棋 題解 [ 藍 ] [ 狀壓 dp ] [ 位運算 ]
- HDU 3006 The Number of set (狀態壓縮)
- 狀壓 + 網路流 -- Escape HDU - 3605
- 論文閱讀 狀態壓縮
- 調和葉狀結構--一個有趣的公式(觀點)公式
- LightOj1296Again Stone Game(手推SG函式)AIGAM函式
- 前端面試每日 3+1 —— 第1021天前端面試
- POJ3279 Fliptile【狀態壓縮+DFS】
- DP套DP
- PAT-B 1021 個位數統計【對映】