lightoj 1021 从当前转移到其他状态的状压dp

来源:互联网 发布:中国股市现状 知乎 编辑:程序博客网 时间:2024/06/05 14:18

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

这个题真是很迷…
看别人的博客才学会的…..
特别是这个状态转移方程我自己想不出来….
通过往括号里加了一项%kk才成立的…
感觉还需要多看几遍….作为dp这个题没啥难点…
是从自己有状态转移到其他没有状态的地方扩展起来这样的….
应该深刻理解….

补充:已经学会了
那个状态转移方程推出来的也不难,之所以只用乘一次base是因为每次转移之前都乘了base所以没有遗漏..
之前就是这里不理解…..
突然就懂了….

#include<iostream>#include<algorithm>#include<cstdio>#include<memory.h>using namespace std;long long  dp[1<<16][20];int jinzhi[200];int tu[21];int main(){    for(int a='0';a<='9';a++)jinzhi[a]=a-'0';    for(int a='A';a<='Z';a++)jinzhi[a]=a-'A'+10;    int T;    cin>>T;    int u=0;    string q;    while(T--)    {        memset(dp,0,sizeof(dp));        int bas,kk;        scanf("%d%d",&bas,&kk);        cin>>q;        memset(tu,0,sizeof(tu));        int len=q.size();        for(int a=0;a<len;a++)tu[a+1]=jinzhi[q[a]];        int zong=1<<len;        dp[0][0]=1;        for(int a=0;a<zong;a++)        {            for(int b=0;b<kk;b++)            {                if(dp[a][b])                {                    for(int c=0;c<len;c++)                    {                        if(a&(1<<c))continue;                        dp[a|(1<<c)][(b*bas+tu[c+1]%kk)%kk]+=dp[a][b];                    }                }            }        }        printf("Case %d: %lld\n",++u,dp[zong-1][0]);    }    return 0;}
0 0
原创粉丝点击