题意:
一个数的值是指这个数位中出现的4和7的次数,比如44就是2,747就是3.现在有7个人,每个人只能拿一个数,每一个数只能被拿一次。你拿的数的值要严格大于其它6个人拿的值,问你有多少种分配方法。
题解:
这个数据范围比较小,那么我们枚举数的值,看看每个值有多少个。之后枚举你拿的值,再dfs6个人拿的值的情况。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
ll num[15];
ll dp[15][15];
int k,a[15];
ll dfs(int pos,int num,int mx)
{
if(pos<=0)
return num==k;
if(~dp[pos][num]&&!mx)
return dp[pos][num];
ll ans=0;
int top=mx?a[pos]:9;
for(int i=0;i<=top;i++)
ans+=dfs(pos-1,num+(i==4||i==7),mx&&i==top);
if(!mx)
dp[pos][num]=ans;
return ans;
}
ll ans;
void dfs2(int pos,int x,ll *b,ll val,ll all)
{
if(pos<=0)
{
ans=(ans+all*val)%mod;
return ;
}
ll ne[15];
for(int i=0;i<=x;i++)
ne[i]=b[i];
for(int i=0;i<=x;i++)
{
if(!ne[i])
continue;
ne[i]--;
dfs2(pos-1,x-i,ne,val*b[i]%mod,all);
ne[i]++;
}
}
int main()
{
ll m;
scanf("%lld",&m);
num[0]=m;
if(m==7)
return 0*printf("0\n");
int x=0;
while(m)
a[++x]=m%10,m/=10;
for(int i=1;i<=x;i++)
{
memset(dp,-1,sizeof(dp));
k=i;
num[i]=dfs(x,0,1);
}
for(int i=1;i<=x;i++)
num[0]-=num[i];
for(int i=x;i>=1;i--)
{
ll nn[15];
for(int i=0;i<x;i++)
nn[i]=num[i];
dfs2(6,i-1,nn,1,num[i]);
}
printf("%lld\n",ans);
return 0;
}