qbxt的题:运

题意:

  包含4,7的数成为幸运数。给一个序列,求多少个长度为k子序列满足:不包含两个及以上的相同的幸运数。(4出现两次就是不合法的,而4,7各出现一次是合法的)。

分析:

  1e9内幸运数只有2^10个,所以可以全搜出来。然后对于序列中出现的幸运数,分别统计其出现的次数。然后对这些幸运数求出合法的方案数就行了。(此处合法是指选的数字满足不能一个数出现两次及以上)。dp[i][j]表示到第i个选了j个幸运数,然后转移即可。

  最后统计答案就是,枚举选了多少个幸运数,用上面的dp数组可以直接得到,然后在非幸运数中随便选了,构成k个即可。

代码: 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cctype>
 6 #include<cmath>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 
14 int read() {
15     int x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch=getchar()) if (ch=='-') f = -1;
16     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0'; return x * f;
17 }
18 
19 #define add(x,y) x+=y, x>=mod?x-=mod:x;
20 const int N = 100005;
21 const int mod = 1e9 + 7;
22 
23 vector<int> num;
24 map<int,int> Id;
25 int cnt[N], a[N], dp[2000][2000], fac[N], ifac[N];
26 
27 void dfs(int x,LL now) {
28     if (x == 11 || now > 1e9) return ; 
29     num.push_back(now);
30     dfs(x + 1, now * 10 + 4);
31     dfs(x + 1, now * 10 + 7);    
32 }
33 
34 int ksm(int a,int b) {
35     int res = 1;
36     while (b) {
37         if (b & 1) res = 1ll * res * a % mod;
38         a = 1ll * a * a % mod;
39         b >>= 1;
40     }
41     return res;
42 }
43 
44 void init(int n) {
45     dfs(1, 0);
46     for (int i = 0; i < num.size(); ++i) Id[num[i]] = i + 1;
47     fac[0] = 1;
48     for (int i = 1; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % mod;
49     ifac[n] = ksm(fac[n], mod - 2);
50     for (int i = n; i >= 1; --i) ifac[i - 1] = 1ll * ifac[i] * i % mod;
51 }
52 
53 int C(int n,int m) {
54     return 1ll * fac[n] * ifac[m] % mod * ifac[n - m] % mod;
55 }
56 
57 int main() {
58     
59     freopen("lucky.in","r",stdin);
60     freopen("lucky.out","w",stdout);
61     
62     init(100000);
63     
64     int n = read(), k = read(), m = num.size(), tot = n;
65     for (int i = 1; i <= n; ++i) {
66         a[i] = read();
67         if (Id[a[i]]) cnt[Id[a[i]]] ++, tot --;
68     }
69     
70     dp[0][0] = 1;
71     for (int i = 1; i <= m; ++i) {
72         for (int j = 0; j <= i; ++j) {
73             if (j) add(dp[i][j], 1ll * dp[i - 1][j - 1] * cnt[i] % mod);
74             add(dp[i][j], dp[i - 1][j]);
75         }
76     }
77     
78     LL ans = 0;
79     int L = max(0, k - m), R = min(k, tot);
80     for (int i = L; i <= R; ++i) {
81         add(ans, 1ll * dp[m][k - i] * C(tot, i) % mod);
82     }
83     
84     cout << ans;
85     return 0;
86 }

 

posted @ 2018-11-01 21:01  MJT12044  阅读(224)  评论(1编辑  收藏  举报