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 }