zoukankan      html  css  js  c++  java
  • bzoj 1072 状压DP

      我们用w[i][j]来表示,i是一个二进制表示我们选取了s中的某些位,j表示这些位%d为j,w[i][j]则表示这样情况下的方案数,那么我们可以得到转移.w[i|(1<<k)][(j*10+s[k]-'0')%d]+=w[i][j]。

      假设s中有x个3,那么我们算出的状态中同样的数我们算了x!次,最后除掉就好了。

    /**************************************************************
        Problem: 1072
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:476 ms
        Memory:12680 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
     
    using namespace std;
     
    int d,cnt[11],w[3010][1010];
    char s[11];
     
    int main() {
        int task; scanf("%d",&task);
        while (task--) {
            scanf("%s%d",s,&d); int len=strlen(s);
            memset(cnt,0,sizeof cnt);
            for (int i=0;i<len;i++) cnt[s[i]-'0']++;
            for (int i=0;i<(1<<len);i++) 
                for (int j=0;j<d;j++) w[i][j]=0;
            w[0][0]=1;
            for (int i=0;i<(1<<len);i++)
                for (int j=0;j<d;j++) if (w[i][j])
                    for (int k=0;k<len;k++) if (!(i&(1<<k)))
                        w[i|(1<<k)][(j*10+s[k]-'0')%d]+=w[i][j];
            int ans=w[(1<<len)-1][0];
            //printf("%d
    ",ans);
            for (int i=0;i<10;i++)
                for (int j=1;j<=cnt[i];j++) {
                    ans/=j ;
                }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    网络协议 19
    网络协议 18
    网络协议 17
    网络协议 16
    网络协议 15
    .NET基础知识(01)-值类型与引用类型
    .NET基础知识(02)-拆箱与装箱
    网络协议 14
    网络协议 13
    网络协议 12
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3679814.html
Copyright © 2011-2022 走看看