bzoj 1072: [SCOI2007]排列perm
2016-06-21
数字 难道是数位DP 可惜不是, 哎n<=10 我竟然没想到是状压DP,
f[i][j]表示i这个状态%d==j的方案数有多少,转移的时候枚举哪一个做最后一位。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 #include<cstdlib> 7 #include<map> 8 #define ll long long 9 #define M 2000009 10 using namespace std; 11 ll read() 12 { 13 char ch=getchar(); 14 ll x=0,f=1; 15 for(;ch<'0'||ch>'9';ch=getchar()) 16 if(ch=='-') 17 f=-1; 18 for(;ch>='0'&&ch<='9';ch=getchar()) 19 x=x*10+ch-'0'; 20 return x*f; 21 } 22 ll a[1024][1009],c[15],D[15]; 23 int b[15],T; 24 int main() 25 { 26 c[0]=1; 27 for(int i=1;i<=10;i++) 28 c[i]=c[i-1]*i; 29 T=read(); 30 for(;T;T--) 31 { 32 memset(D,0,sizeof(D)); 33 char ch[15]; 34 scanf("%s",ch); 35 int n=strlen(ch); 36 for(int i=0;i<n;i++) 37 { 38 b[i]=ch[i]-'0'; 39 D[b[i]]++; 40 } 41 int d=read(); 42 int S=(1<<n); 43 memset(a,0,sizeof(a)); 44 a[0][0]=1; 45 for(int i=1;i<S;i++) 46 for(int j=0;j<n;j++) 47 if(i&(1<<j)) 48 for(int k=0;k<d;k++) 49 a[i][(k*10+b[j])%d]=a[i-(1<<j)][k]+a[i][(k*10+b[j])%d]; 50 ll an=a[S-1][0]; 51 for(int i=0;i<=9;i++) 52 an/=c[D[i]]; 53 printf("%lld\n",an); 54 } 55 return 0; 56 }