题目大意:给定n个数字,求这些数字的全排列中有多少数能被d整除
令f[i][j]为状态为i,余数为j的方案数
枚举最高位转移
小心爆int
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,d,ans,f[1<<10][1<<10],digit[1<<10],tens[10],cnt[10],factorial[11]; char s[20]; int Get_Digit(int x) { int re=0; while(x) re+=x&1,x>>=1; return re; } void State_Compressed_DP(int x) { int i,j; if(x==1023) ++x,--x; for(i=0;i<n;i++) if(1<<i&x) { int temp=tens[digit[x]-1]%d*(s[i]-'0')%d; for(j=0;j<d;j++) f[x][(j+temp)%d]+=f[1<<i^x][j]; } } int main() { int T,i; for(i=0;i<1<<10;i++) digit[i]=Get_Digit(i); tens[0]=1; for(i=1;i<10;i++) tens[i]=tens[i-1]*10; factorial[0]=1; for(i=1;i<=10;i++) factorial[i]=factorial[i-1]*i; for(cin>>T;T;T--) { memset(f,0,sizeof f); scanf("%s%d",s,&d); n=strlen(s); f[0][0]=1; for(i=1;i<1<<n;i++) State_Compressed_DP(i); ans=f[(1<<n)-1][0]; memset(cnt,0,sizeof cnt); for(i=0;i<n;i++) cnt[s[i]-'0']++; for(i=0;i<=9;i++) ans/=factorial[cnt[i]]; cout<<ans<<endl; } }
BZOJ 1072 SCOI2007 排列perm 状压DP
原文地址:http://blog.csdn.net/popoqqq/article/details/40142641