zoukankan      html  css  js  c++  java
  • [ SCOI 2007 ] Perm

    (\)

    (Description)


    给出只包括多个(0 ext~ 9)的数字集,求有多少个本质不同的全排列,使得组成的数字能够整除(M)

    • (|S|in [1,10])(Min [1,10^3])

    (\)

    (Solution)


    • 一眼状压,先将所有数字看作互不相同,(f[S][k])表示集合内数字选取情况为(S),当前组成的数对(M)取模的结果为(k)的方案数,显然边界(f[0][0]=1)
    • 枚举补集里的元素扩展,每次注意余数改为((k*10+a[j])\%M)
    • 注意到每一个答案最后都用到了所有的数,所以所有相同的数最后在每一个答案里都会出现全排列,也就是说答案为(f[S_{max}][0])除掉每一个数的全排列后的答案。

    (\)

    (Code)


    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 1050
    #define R register
    #define gc getchar
    using namespace std;
     
    int n,m,t,tot,a[10],p[10],num[10],f[N][N];
     
    int main(){
      scanf("%d",&t);
      while(t--){
        char c=gc(); m=0;
        for(R int i=0;i<=9;++i) p[i]=1,num[i]=0;
        while(!isdigit(c)) c=gc();
        a[tot=1]=c^48; ++num[a[1]];
        while(isdigit(c=gc())) ++num[a[++tot]=c^48];
        for(R int i=0;i<=9;++i)
          for(R int j=1;j<=num[i];++j) p[i]*=j;
        while(!isdigit(c)) c=gc();
        while(isdigit(c)){
          m=(m<<1)+(m<<3)+(c^48); c=gc();
        }
        for(R int i=0;i<(1<<tot);++i)
          for(R int j=0;j<m;++j) f[i][j]=0;
        f[0][0]=1;
        for(R int i=0;i<(1<<tot);++i)
          for(R int j=0;j<m;++j) if(f[i][j]){
            for(R int k=0;k<tot;++k)
              if(!(i&(1<<k))) f[i|(1<<k)][(j*10+a[k+1])%m]+=f[i][j];
          }
        for(R int i=0;i<=9;++i) f[(1<<tot)-1][0]/=p[i];
        printf("%d
    ",f[(1<<tot)-1][0]);
      }
      return 0;
    }
    
  • 相关阅读:
    壶公随感
    消息称微软受谷歌刺激 急于收购雅虎(zz)
    远程注销Windows用户
    "杀人"游戏中的一些规律
    由两点的经纬度估算距离
    我的城市?
    Blog里的一个bug,dudu看能否修正?
    这两天真烦
    发简历,找上海.Net方面软件开发工作
    "上海.NET俱乐部"聚会筹备进展
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9590136.html
Copyright © 2011-2022 走看看