Codeforces Round #235 (Div. 2) D. Roman and Numbers (pressure dp ),
Roman and Numberstime limit per test4 secondsmemory limit per test512 megabytesinputstandard inputoutputstandard output
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 numberN, ModuloM.
NumberXIs considered close to numberNModuloM, If:
- It can be obtained by rearranging the digits of numberN,
- It doesn' t have any leading zeroes,
- The remainder after dividing numberXByMEquals 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 digit ≤ DigitNBetween <limit 1018) andM(1 digit ≤ DigitMLimit ≤ limit 100 ).
Output
In a single line print a single integer-the number of numbers close to numberNModuloM.
Sample test (s) input
104 2
Output
3
Input
223 4
Output
1
Input
7067678 8
Output
47
Note
In the first sample the required numbers are: 104,140,410.
In the second sample the requirednumber is 232.
Question: Give the numbers num and m, and ask how many numbers (mod m) = 0 in the "num" column are rearranged. It is definitely not possible to directly list all numbers, you can press dp to do this ..
Dp [S] [k] indicates the number of solutions with S in num selected and (mod m) = k selected. The initial condition is dp [0] [0] = 1, the transferor is dp [I | 1 <j [(10 * k + num [j]) % m] + = dp [I} [k];. Note that there are multiple permutation, so we also need to remove duplicates. The Code is as follows:
# Include <iostream> # include <cstring> using namespace std; typedef long ll; ll dp [1 <18] [100], c [20]; // dp [S] [k] indicates the number of solutions int main (int argc, char const * argv []) with S in num selected and (mod m) = k selected {char num [20]; int m; while (cin> num> m) {memset (dp, 0, sizeof dp); memset (c, 0, sizeof c); dp [0] [0] = 1; ll div = 1, sz = strlen (num), t = 1 <sz; for (int I = 0; I <sz; I ++) {div * = (++ c [num [I]-= '0']); // rearrange the last Division n1! * N2! *... Nk !} For (int I = 0; I <t; I ++) {for (int j = 0; j <sz; j ++) if (! (I & 1 <j) {// if (num [j] | I) is transferred only when j IS NOT INCLUDED IN set S) {// At least one is not 0 and no leading 0for (int k = 0; k <m; k ++) {dp [I | 1 <j] [(10 * k + num [j]) % m] + = dp [I] [k] ;}} cout <dp [T-1] [0]/div <endl;} return 0 ;}