CodeForces 401D 數位DP

life4711發表於2015-11-04

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=98182#problem/D

Description

Roman is a young mathematician, very famous in Uzhland. Unfortunately, Sereja doesn't think so. To make Sereja change his mind, Roman is ready to solve any mathematical problem. After some thought, Sereja asked Roma to find, how many numbers are close to number n, modulo m.

Number x is considered close to number n modulo m, if:

  • it can be obtained by rearranging the digits of number n,
  • it doesn't have any leading zeroes,
  • the remainder after dividing number x by m equals 0.

Roman is a good mathematician, but the number of such numbers is too huge for him. So he asks you to help him.

Input

The first line contains two integers: n(1 ≤ n < 1018) and m(1 ≤ m ≤ 100).

Output

In a single line print a single integer — the number of numbers close to number n modulo m.

Sample Input

Input
104 2
Output
3
Input
223 4
Output
1
Input
7067678 8
Output
47

Hint

In the first sample the required numbers are: 104, 140, 410.

In the second sample the required number is 232.

/**
CodeForces 401D  數位DP
題目大意:給定一個數字n,將其所有的位上的數重組後組成新的數,問重組後的數有多少個是m的倍數
解題思路:一開始想著統計0~9十個數各出現了多少個,然後普通dp的,費了半天勁,後來覺得狀態太大無法表示,才想到用數位dp。dp[s][k]表示每個數位上的數使用的狀態為s(5二進位制表示101,那麼就是第一三位上的數已使用,第二位上的數沒有使用)
          當前數對m的取模為k的數有多少個。有一個問題就是如果直接dp會重複取的,比如:111 3 答案是1而不是6,那麼用一個
          flag陣列表示第i位上bit[i]已用就不會出現重複取的情況了,然後dp一下就可以了。數位dp我用的kuangbin的模板
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;

LL dp[(1<<19)+5][111],n;
int m,bit[25],len;

LL dfs(int pos,int s,int k)
{
    if(pos<0&&(s==(1<<len)-1))return (k==0);
    if(dp[s][k]!=-1)return dp[s][k];
    LL ans=0;
    int flag[10];
    memset(flag,0,sizeof(flag));
    for(int i=0;i<len;i++)
    {
        if((s&(1<<i))==0&&flag[bit[i]]==0)
        {
            flag[bit[i]]=1;
            ans+=dfs(pos-1,s|(1<<i),(k*10+bit[i])%m);
        }
    }
    dp[s][k]=ans;
    return ans;
}

LL solve(LL n)
{
    int k=0;
    while(n)
    {
        bit[k++]=n%10;
        n/=10;
    }
    len=k;
    int s=0;
    LL ans=0;
    int flag[10];
    memset(flag,0,sizeof(flag));
    for(int i=0;i<len;i++)
    {
        if(bit[i]&&flag[bit[i]]==0)
        {
             flag[bit[i]]=1;
            ans+=dfs(k-2,s|(1<<i),bit[i]%m);
        }
    }
    return ans;
}
int main()
{
    while(~scanf("%I64d%d",&n,&m))
    {
        memset(dp,-1,sizeof(dp));
        printf("%I64d\n",solve(n));
    }
    return 0;
}
/**
123 3

104 2

401 2

7067678 8
*/


相關文章