10.17T2 状压DP

H-C-H的烦恼

Problem Background

众所周知,亚甲基太强了

%%%%%%%%%%%%%

Problem Discription

CH 2 作为一个有机二价能团,现在,他要和其他原子团化合。具体来说,有n个原子 团,最多被分为10种,编号分别为0-9CH 2 有一个幸运数字P,如果这n个原子团编号的一种 排列所表示的数能够被P整除,那么CH2就认为这是一个优美化合数。CH2想知道有多少个优美 化合数,但他还要忙着去参加IOIWorld Final,这个问题就交给你了。

Input

仅一行n个数组成的的字符串S和一个整数P

S中每个数表示该原子团的种类

Output

一行,输出优美化合数的个数

SampleInput

1224 7

Sample Output

2

Hint

1,2,2,4 的排列能够表示的数有

1224,1242,1422,2124,2142,2214,2241,2412,2421,4221,4212,4122

其中,21424221能被7整除,答案为2

DataScale

测试点编号

n

P

特殊性质

1

4

≤10

 

2

5

≤10

 

3

6

≤100

A/B

4

7

≤100

A/B

5

10

≤300

A

6

10

≤300

 

7

≤15

=2

B

8

≤15

=2

 

9

18

=3

 

10

18

=5

 

11

15

=25

 

12

12

≤300

B

13

12

≤300

B

14

16

≤50

B/C

15

16

≤100

C

16

16

300

 

17

18

50

B/C

18

18

50

C

19

18

50

 

20

18

50

 

特殊性质约定:

A:不存在重复数字

B:不存在0

C:最多出现3种数字

设f[i][j]表示状态为i,模数为j的方案数,此题转移方程在代码里就很显然了

注意因为有重复的数字所以要除以每一个数字个数的阶乘

然后我们就做完了(我其实想到了但是神tm多加了一个维度55555,我菜啊,本来可以AC的55555)

code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 using namespace std;
 5 string k;
 6 long long P,num[10],fac[20],f[400000][300];
 7 int main(){
 8     cin>>k>>P;
 9     long long all=(1<<k.size())-1;
10     f[0][0]=1;
11     for(long long i=0;i<=all;i++)
12         for(long long rest=0;rest<P;rest++)
13             for(long long j=0;j<k.size();j++)
14                 if(((i>>j)&1)==0)
15                     f[i|(1<<j)][(rest*10+k[j]-'0')%P]+=f[i][rest];
16     for(long long i=0;i<k.size();i++)num[k[i]-'0']++;    
17     fac[0]=1;
18     for(long long i=1;i<=k.size();i++)fac[i]=fac[i-1]*i;
19     for(long long i=0;i<=9;i++)f[all][0]/=fac[num[i]];
20     cout<<f[all][0];
21     return 0;
22 }

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9804506.html