题目链接:
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; }