码迷,mamicode.com
首页 > 其他好文 > 详细

「Algospot」津巴布韦ZIMBABWE

时间:2019-02-05 10:40:30      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:dfs   size   continue   --   理解   gis   cst   语言   ace   

同时考验对状压DP和数位DP的理解;

传送门:$>here<$

题意

给出一个数字$e$,现在对$e$通过$m$进行变换得到$x$;变换的要求是:1.只能改变原数字$e$各个数位的顺序(可以有前导零) 2.$x$是$m$的倍数 3. $x<e$

问$x$有几种取值满足?

数据范围:$e \leq 10^14, m \leq 20$

Solution

DFS怎么做是关键

这道题如果使用DFS,那么大体思路就是枚举每一位填放什么数字。

那么需要一个数组(状压)在此过程中来记录还可以用哪些数字。这个地方不要想太多,我起初的思路刚开始统计一格数组代表0~9每个数字有几个,再依次减。然而这样麻烦,而且无法状压。一个直接的思路是直接用一个布尔数组表示原数组的每一位是否被用掉。

光这样是不行的,我们忘记考虑重复问题了。即$e=422$时,枚举每一位填什么时程序会把每个数字看成不同的,也就会出现$224,242,224,242$四种情况。

解决重复问题

如果按照我刚开始的思路把0~9各位统计出来就没这样的问题了。于是考虑能不能在状压的情况下也能达成这种效果。把$e$中各位进行排序得到$num$数组。这样的话,每当我使用一个数字的时候,先去检查在它之前的相同数字是否已被使用完——相当于把每种数字弄成一个栈,每次只能取栈顶。

转化为程序语言,就是满足一下三个条件中的一个:

1. 当前数字是$num$中的首个(特判第一个数字的栈顶)

2. 当前数字与前面那个数字不同(还未使用过的某个数字的栈顶)

3. 当前数字前面的那个已被用过(使用过的某个数字的栈顶)

……

透过题解看本质

……

my code

……

/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 20010;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
    int x = 0; int w = 1; register char c = getchar();
    for(; c ^ - && (c < 0 || c > 9); c = getchar());
    if(c == -) w = -1, c = getchar();
    for(; c >= 0 && c <= 9; c = getchar()) x = (x<<3) + (x<<1) + c - 0; return x * w;
}
char s[300];
int T,m,len,digit[300],num[300],e[300],dp[40010][30][2];
int dfs(int cur, int sta, int mo, bool lim){
    if(cur == len){
        if(mo==0 && lim==0){
            return 1;
        }  
        else{
            return 0;
        }
    }
    int& a = dp[sta][mo][lim];
    if(a != -1) return a;
    a = 0;
    for(int i = 0; i < len; ++i){
        if(lim && num[i] > e[cur]) break;
        if(sta & (1<<i)) continue;
        if(i==0 || num[i]!=num[i-1] || (sta & (1<<(i-1)))){
            digit[cur] = num[i];
            a = (a + dfs(cur+1, sta|(1<<i), (mo*10+num[i])%m, lim&(num[i]==e[cur]))) % MOD;
        }
    }
    return a;
}
int main(){
    scanf("%d",&T);
    while(T--){
        memset(dp,-1,sizeof(dp));
        memset(digit,0,sizeof(digit));
        scanf("%s",s);
        scanf("%d",&m);
        len = strlen(s);
        for(int i = 0; i < len; ++i){
            e[i] = s[i] - 0;
            num[i] = e[i];
        }
        sort(num,num+len);
        printf("%d\n",dfs(0,0,0,1));
    }
    return 0;
}

「Algospot」津巴布韦ZIMBABWE

标签:dfs   size   continue   --   理解   gis   cst   语言   ace   

原文地址:https://www.cnblogs.com/qixingzhi/p/10352529.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!