题意:给出数n,m.问有多少个x 满足x%m==0 x和n包含相同的数字(无前导0,顺序可以不同)?
n<=1e18,m<=100.4s时限
最多18位数字,用18位二进制表示当前状态,第i位为1则表示n的第i位数字被使用,答案为dp[(1<<18)-1][0]]
按最后一个添加进集合的数字转移状态,注意(a[1],a[3]) (a[3],a[1])被重复计算 答案在除以每个数字出现次数的排列.
n<=1e18,m<=100.4s时限
最多18位数字,用18位二进制表示当前状态,第i位为1则表示n的第i位数字被使用,答案为dp[(1<<18)-1][0]]
按最后一个添加进集合的数字转移状态,注意(a[1],a[3]) (a[3],a[1])被重复计算 答案在除以每个数字出现次数的排列.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1<<19;
ll n,m,dp[N][101],cnt[20],f[20];
ll a[20],pos;
void init()
{
pos=0;
memset(cnt,0,sizeof(cnt));
while(n)
{
a[pos++]=n%10;
cnt[n%10]++;
n/=10;
}
}
int main()
{
f[0]=1;
for(int i=1;i<20;i++)
f[i]=f[i-1]*(ll)i;
while(cin>>n>>m)
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
init();
int s=1<<pos;
for(int i=0;i<s;i++)
{
for(int j=0;j<m;j++)
{
for(int k=0;k<pos;k++)
{
if((i>>k)&1)
continue;
if(i==0&&a[k]==0)
continue;
dp[i|1<<k][(j*10+a[k])%m]+=dp[i][j];
}
}
}
ll ans=dp[s-1][0];
for(int i=0;i<=9;i++)
ans/=f[cnt[i]];
cout<<ans<<endl;
}
return 0;
}