10.17T2 状压DP
H-C-H的烦恼
Problem Background
众所周知,亚甲基太强了
%%%%%%%%%%%%%
Problem Discription
CH 2 基作为一个有机二价官能团,现在,他要和其他原子团化合。具体来说,有n个原子 团,最多被分为10种,编号分别为0-9,CH 2 有一个幸运数字P,如果这n个原子团编号的一种 排列所表示的数能够被P整除,那么CH2就认为这是一个优美化合数。CH2想知道有多少个优美 化合数,但他还要忙着去参加IOI和World 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
其中,2142和4221能被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