题目链接:
http://codeforces.com/problemset/problem/258/B
题目意思:
给你一个m(m<=1^9),把1-m这m个数拿出7个分给7个政党,要求其中一个政党分配的数中含4和7的总个数比其他6个政党含4和7的总数还要多,求分配的总的种数,对1000000007求余。
解题思路:
先用数位dp,求出含有0个4或7的数的个数,含有1个4或7的数的个数,含。。。。。
dp[cur][last][sum]:表示还有cur位,前面一共含有last个4或者7,总共要求含有sum个4或者7的总的个数
然后分配的时候用递归来实现,其中组合数求余用到了求逆元的方法。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF (1<<30)
#define PI acos(-1.0)
using namespace std;
#define mod 1000000007
#define ll __int64
int num[15];
int dp[15][15][15],pos[15];
int dfs1(int cur,int last,int sum,int flag)
{
if(!cur)
{
if(last==sum)
return 1;
return 0;
}
if(last>sum)
return 0;
if(!flag&&dp[cur][last][sum]!=-1)
{
return dp[cur][last][sum];
}
int Max=flag?pos[cur]:9,numm=0;
for(int i=0;i<=Max;i++)
{
if(i==7||i==4)
numm+=dfs1(cur-1,last+1,sum,flag&&i==Max);
else
numm+=dfs1(cur-1,last,sum,flag&&i==Max);
}
if(!flag)
dp[cur][last][sum]=numm;
return numm;
}
void Cal(int m)
{
int tt=0;
while(m)
{
++tt;
pos[tt]=m%10;
m/=10;
}
for(int i=0;i<=9;i++) //表示含有i个4或者7的总数
num[i]=dfs1(tt,0,i,1);
}
ll AA(int n,int m)
{
ll res=1;
for(int i=n;i>=n-m+1;i--)
res=(res*i)%mod;
return res;
}
ll quick(ll m,ll n) //快速幂求m^n%mod
{
ll res=1;
while(n)
{
if(n&1)
res=(res*m)%mod;
m=(m*m)%mod;
n=n>>1;
}
return res;
}
ll CC(int n,int m) //求组合数C(n,m)
{
ll res=AA(n,m);
ll temp=1;
for(int i=2;i<=m;i++)
temp=(temp*i)%mod;
return (res*quick(temp,mod-2))%mod;
}
ll dfs2(int start,int sum,int left) //搜索求总的排列数
{
if(left==0) //选出了6个政党
return AA(6,6); //A66 采用先选后排的方法
if(start<0) //不够
return 0;
ll res=0;
for(int i=0;i<=num[start]&&(start*i)<sum&&i<=left;i++)
res=(res+(CC(num[start],i)*dfs2(start-1,sum-start*i,left-i))%mod)%mod;
return res;
}
int main()
{
int m;
memset(dp,-1,sizeof(dp));
while(scanf("%d",&m)!=EOF)
{
memset(num,0,sizeof(num));
Cal(m);
num[0]--; //题目要求从1-m
ll ans=0;
for(int i=9;i>=1;i--)
if(num[i])
ans=(ans+(num[i]*dfs2(i-1,i,6))%mod)%mod;
printf("%I64d\n",ans);
}
return 0;
}