• [ 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;
    }
    
  • 相关阅读:
    python2和python3中TestSuite().addTest的区别
    python2和python3中range的区别
    WebDriverAgent安装
    Charles IOS https抓包
    Python和 pytest的异常处理
    Python中yaml和json文件的读取和应用
    Python 获取当前文件所在路径
    自建包函数调用
    python的logging,将log保存到文件
    泛型
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9590136.html
Copyright © 2020-2023  润新知