CF401D Roman and Numbers 状压DP

CF401D

meaning translation

Rearrange the digits of n(n<=10^18) (leading zeros are not allowed) Find out how many numbers mod m can be constructed equal to 0

Topic 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 n n , modulo m m m .

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

  • it can be obtained by rearranging the digits of number n n n ,
  • it doesn't have any leading zeroes,
  • the remainder after dividing number x x x by m m 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 and output format

Input format:

The first line contains two integers: n n n $ (1<=n<10^{18}) $ and m m m (1<=m<=100) (1<=m<=100) (1<=m<=100) .

Output format:

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

Input and output example

Input example #1: 
104 2
Sample output #1: 
3
Input example #2: 
223 4
Sample output #2: 
1
Input example #3: 
7067678 8
Sample output #3: 
47

illustrate

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

In the second sample the required number is 232.

 

analyze:

The title description is really scary, how many %m == 0 numbers can be created by rearranging n-digit numbers;
In fact, it is state compression;
Define f [i] [j] , i represents a binary number, 1 represents the number selected, j represents the number consisting of x selected from n numbers %m==j;
 

Transition equation: f[i|(1 << k)][(j * 10 + x) % m] += f[i][j];

 

Meaning: For the kth digit x, you can switch from not selecting him to selecting him, that is, i -> i | (1 << k);

Then the second dimension is given by j -> (j *10 + x) % m (obviously);

 

Note: Because state compression is violent, each digit is regarded as different from the previous number, such as 11, which should be counted once, but we counted twice;

Solution: 1. Finally divide by cnt! (cnt is how many times a number appears).

    2. Deduplication directly.

Here is the code:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn (1 << 18) + 5
#define int long long

int n, m;

int s[21];

int f[maxn][105];

char ch[20];

bool fish [20];

signed main()
{
	scanf("%s%lld", &ch, &m);
	
	int n = strlen(ch);
	
	f[0][0] = 1;
	
	int e = (1 << n);
	for(register int i = 0 ; i < e ; i ++)
	{
		for(register int j = 0 ; j < m ; j ++)
		{
			memset(vis, 0, sizeof vis);
			for(register int k = 0 ; k < n ; k ++)
			{
				int x = ch[k] - '0';
				if(i & (1 << k)) continue;
				if(i == 0 && x == 0) continue;
				if(vis[x]) continue;
				screw[x] = 1;
				f[i|(1<<k)][(j*10+x)%m] += f[i][j];
			}
		}
	}
	
	cout << f[e-1][0];
	return 0;

	
}

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324885166&siteId=291194637