首页 > 代码库 > BZOJ 1072 SCOI2007 排列perm 状压DP
BZOJ 1072 SCOI2007 排列perm 状压DP
题目大意:给定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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。