BZOJ 1072 排列

Posted on 2017-03-14 09:28  ziliuziliu  阅读(120)  评论(0编辑  收藏  举报

状压。最后除一下每个数出现次数的阶乘。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long t,dp[1050][1050],cnt[15],d,tab[15],mm[15];
char s[15];
long long bit_count(long long x)
{
    long long ret=0;
    while (x)
    {
        if (x&1) ret++;
        x>>=1;
    }
    return ret;
}
void work()
{
    scanf("%s",s);scanf("%lld",&d);
    tab[0]=1;for (long long i=1;i<=10;i++) tab[i]=(tab[i-1]*10)%d;
    memset(dp,0,sizeof(dp));memset(cnt,0,sizeof(cnt));
    long long l=strlen(s);
    for (long long i=0;i<l;i++) cnt[s[i]-'0']++;
    dp[0][0]=1;
    for (long long i=1;i<(1<<l);i++)
    {
        long long ret=bit_count(i),nb=s[ret-1]-'0';
        for (long long j=0;j<l;j++)
        {
            if (i&(1<<j))
            {
                for (long long k=0;k<d;k++)
                    dp[i][k]+=dp[i^(1<<j)][(k-tab[j]*nb%d+d)%d];
            }
        }
    }
    for (long long i=0;i<=9;i++) dp[(1<<l)-1][0]/=mm[cnt[i]];
    printf("%lld\n",dp[(1<<l)-1][0]);
}
int main()
{
    scanf("%lld",&t);
    mm[0]=mm[1]=1;for (long long i=2;i<=10;i++) mm[i]=mm[i-1]*i;
    for (long long i=1;i<=t;i++) work();
    return 0;
}