状压。最后除一下每个数出现次数的阶乘。
#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; }