P--运(lucky)
来源:互联网 发布:淘宝新店铺有扶持吗 编辑:程序博客网 时间:2024/05/18 03:56
【问题背景】
zhx和妹子们玩数数游戏。
【问题描述】
仅包含4或7的数被称为幸运数。
一个序列的子序列被定义为从序列中删去若干个数,剩下的数组成的新序列。两个子序列被定义为不同的当且仅当其中的元素在原始序列中的下标的集合不相等。对于一个长度为N的序列,共有2N 个不同的子序列。(包含一个空序列)。
一个子序列被称为不幸运的,当且仅当其中不包含两个相同的幸运数。
对于一个给定序列,求其中长度恰好为K的不幸运子序列的个数,答案mod109+7 输出。
【输入格式】
第一行两个正整数N,K,表示原始序列的长度和题目中的K。
接下来一行N个整数ai,表示序列中第i个元素的值。
【输出格式】
仅一个数,表示不幸运子序列的个数。(mod 10^9+7)
【样例输入】
3 2
1 1 14 2
4 7 4 7
【样例输出】
3
4
【样例解释】
对于样例1,每个长度为2的子序列都是符合条件的。
对于样例2,4个不幸运子序列元素下标分别为:{1, 2}, {3, 4}, {1, 4}, {2, 3}。注意下标集{1, 3}对应的子序列不是“不幸运”的,因为它包含两个相同的幸运数4.
【数据范围与规定】
此题良心,暴力拿高分,不过我们并不打算写暴力……对于50%的数据,
1≤N≤16 。
对于70%的数据,1≤N≤1000,ai≤10000 。
对于100%的数据,1≤N≤100000,K≤N,1≤ai≤109 。
注意到幸运数的个数很少,我们可以处理出每个幸运数的个数。
然后考虑非幸运数字,显然是一个组合数问题,这样总共就有(幸运数种数为tot,非幸运数个数为d):
∑i=1min(tot,k)Ck−id∗calc(tot,i)
的方案数了,对于calc数组DP处理:设dp[i][j]=从前i个幸运数中选j个的方案数,因为对于一种幸运数,要么选一个要么不选,因此即有以下dp方程(C[i]=离散后第i种幸运数的个数):
dp[i][j]=dp[i−1][j]+dp[i−1][j−1]∗C[i]
注意初值:
dp[i][0]=1(0<=i<=tot)
此问题解决,综上复杂度O(m^2+n),代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <map>#define M 100005#define P 1000000007using namespace std;inline int read(void){int x=0,f=1; char ch=getchar();for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;for(;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+ch-'0',ch=getchar());return x*f;}const int maxn=2009;map<int,int>mp;int fact[M],dp[maxn][maxn];int A[M],C[M];inline bool check(int x){ if(!x) return false; while(x){ int d=x%10; x/=10; if(d!=4&&d!=7) return false; } return true;}inline int fast(int a,int b){int ans=1;for(;b;b>>=1,a=1LL*a*a%P)if(b&1) ans=1LL*ans*a%P;return ans;}int Calc(int n,int m){ if(n>m) return 0; return 1LL*fact[m]*fast(fact[m-n],P-2)%P*fast(fact[n],P-2)%P;}inline void Check(int &a,int b){ a+=b; if(a>P) a%=P;}int main(int argc,char const *argv[]){ int n=read(),k=read(); int tot=0,ans=0,d=0; for(int i=1;i<=n;i++){ A[i]=read(); if(check(A[i])) mp[A[i]]++; else d++; } fact[0]=1; for(int i=1;i<=n;i++) fact[i]=1LL*fact[i-1]*i%P; for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++) C[++tot]=it->second; for(int i=0;i<=tot;i++) dp[i][0]=1; for(int i=1;i<=tot;i++) for(int j=1;j<=i;j++){ Check(dp[i][j],dp[i-1][j]); Check(dp[i][j],1LL*dp[i-1][j-1]*C[i]%P); } for(int i=0;i<=min(tot,k);i++) ans=(ans+1LL*dp[tot][i]*Calc(k-i,d))%P; printf("%d\n",ans); return 0;}
- P--运(lucky)
- 运lucky
- Betmalay | iBET Lucky Draw Free Poker Card(Betmalay, Free Pocker Card, iBET Lucky Draw, Lucky Draw P
- Lucky Numbers(acm)
- lucky
- *p++,*++p,++*p(转载)
- *p++ 和 (*p)++
- lucky number(hdu 3346)
- CODEFORCES630C- Lucky Numbers(水题)
- HDU - 5665 Lucky (技巧)
- Codeforces 110B-Lucky String(技巧)
- 【HDU】5213 Lucky 【分块(在线算法)】
- hdu 5213 Lucky(容斥+莫队)
- POJ-2346 Lucky tickets(线性DP)
- hihoCoder_W84 Lucky Substrings(基础做法)
- CodeForces 630 C. Lucky Numbers(水~)
- HDU 5665 Lucky(思维题)【BC】
- 2016-scut-H. Lucky Array(分块)
- 1578: [Usaco2009 Feb]Stock Market 股票市场
- D3系列第五弹——绘制树状图
- 1927: [Sdoi2010]星际竞速
- Hadoop mapper类的阅读
- 王爽汇编语言 检测点11.4
- P--运(lucky)
- 1144. 陶陶摘苹果
- [C++] Boost智能指针——boost::scoped_ptr(使用及原理分析)
- c++基础之字符串
- maven常用命令介绍
- ccf认证最优配餐80分
- Unity5.0 Shader 极简入门 (四)
- P1133 教主的花园
- point类求两点间的距离,点到原点的距离