K - Painful Bases 状压dp

Painful Bases

 LightOJ - 1021 

这个题目一开始看,感觉有点像数位dp,但是因为是最多有16进制,因为限制了每一个数字都不同最多就有16个数。

所以可以用状压dp,看网上题解是

dp[s][r] 表示数字集合为s,对 k 取余为r的方案数。

这个题目首先把给你的字符转化成数字,然后枚举状态,枚举模数,枚举每一位的所有可能。

这个注意是写离散化的,不是直接暴力,虽然理论上都会超时,但是实际上离散化的没有超时。

这个题目我觉得还挺好的,以后可以在写写

#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\n", cas,dp[(1 << len) - 1][0]);
    }
    return 0;
}
状压dp

 

排列perm

 HYSBZ - 1072 

这个题目和上面的差不多,有一个小地方注意一下,就是这个有相同的所以要除去。

#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\n", dp[(1<<len)-1][0]/ans);
    }
    return 0;
}
状压

 

posted @ 2019-07-27 14:55  EchoZQN  阅读(156)  评论(0编辑  收藏  举报