• 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;
    }
    
  • 相关阅读:
    ASP.NET连接数据库配置文件
    ASP.NET应用程序的文件类型及文件夹列表
    c#配置文件的简单操作
    js加载XML文件
    c#生成动态库并加载
    class和id的区别
    Div和Span的区别
    C#类和对象
    C#表达式和语句
    函数声明提升和变量提升
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580597.html
Copyright © 2020-2023  润新知