zoukankan      html  css  js  c++  java
  • LightOJ 1021 Painful Bases 【状压DP+数位DP】

    题目链接

    题意

    求由一些B进制的数的全排列中能被K整除的数的个数

    分析

    题中B最高达到16,直接枚举排列显然不可能。考虑数位DP,但同时取得每个数要不同,所以需要记录用过哪些数,因此要用到状压DP

    状态

    dp[S][r]{S}Kr

    转移方程

    dp[S][r]=a{S}dp[S{a}][r]

    其中 (r+a×Bt1%k)%k=r (t为S中元素个数)

    另外注意base的幂要预处理,不然会T

    AC代码

    //LightOJ 1021 Painful Bases
    //AC 2016-08-04 15:02:54
    //DP
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <string>
    #include <map>
    #include <queue>
    #include <deque>
    #include <list>
    #include <sstream>
    #include <stack>
    using namespace std;
    
    #define cls(x) memset(x,0,sizeof x)
    #define inf(x) memset(x,0x3f,sizeof x)
    #define neg(x) memset(x,-1,sizeof x)
    #define ninf(x) memset(x,0xc0,sizeof x)
    #define st0(x) memset(x,false,sizeof x)
    #define st1(x) memset(x,true,sizeof x)
    #define INF 0x3f3f3f3f
    #define lowbit(x) x&(-x)
    #define input(x) scanf("%d",&(x))
    #define bug cout<<"here"<<endl;
    //#define debug
    
    unsigned long long dp[(1<<17)][30];
    char org[20];
    int num[20];
    int T,B,K;
    
    int Pow(int x,int y)
    {
        int res=1;
        for(int i=0;i<y;++i)
            res=(res%K*x%K)%K;
        return res%K;
    }
    int pows[20];
    
    int main()
    {
        #ifdef debug
            freopen("E:\Documents\code\input.txt","r",stdin);
            freopen("E:\Documents\code\output.txt","w",stdout);
        #endif
        input(T);
        for(int kase=1;kase<=T;++kase)
        {
            input(B);input(K);
            scanf("%s",org);
            int len=strlen(org);
            for(int i=0;i<len;++i)
            {
                if(isdigit(org[i]))
                    num[i]=org[i]-'0';
                else
                    num[i]=org[i]-'A'+10;
            }
            cls(dp);
            dp[0][0]=1;
            for(int i=0;i<=len;++i)
                pows[i]=Pow(B,i);
            for(int i=0;i<(1<<len)-1;++i)
            {
                int t=0;
                for(int j=0;j<len;++j)
                    if((i>>j)&1) ++t;
                for(int j=0;j<len;++j)
                {
                    if((i>>j)&1) continue;
                    for(int r=0;r<K;++r)
                    {
                        int r1=((r+(num[j]%K)*pows[t])%K)%K;
                        dp[i|(1<<j)][r1]+=dp[i][r];
                    }
                }
            }
            printf("Case %d: ",kase);
            cout<<dp[(1<<len)-1][0]<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    leetcode 78. 子集 JAVA
    leetcode 91. 解码方法 JAVA
    leetcode 75. 颜色分类 JAVA
    leetcode 74 搜索二维矩阵 java
    leetcode 84. 柱状图中最大的矩形 JAVA
    last occurance
    first occurance
    classical binary search
    LC.234.Palindrome Linked List
    LC.142. Linked List Cycle II
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580597.html
Copyright © 2011-2022 走看看