CodeForces 146E - Lucky Subsequence DP+扩展欧几里德求逆元
题意:
一个数只含有4,7就是lucky数...现在有一串长度为n的数...问这列数有多少个长度为k子串..这些子串不含两个相同的lucky数...
子串的定义..是从这列数中选出的数..只要序号不同..就不不同的串..如 1 1 的长度为1的子串有两个
题解:
解题前可以先求一下1000000000内有多少个数是lucky的...可以递推的求..也可以暴力求~~可以看出最多1022个lucky数..很少...
现将这堆数的所有lucky数找出来...把相同的放在一个lucky数里计数...
dp[ i ] [ k ] 代表到了第i个lucky数..选了k个lucky数的方案总数...
dp全部处理完后统计答案:
ans= sigma ( dp [ last ] [ i ] + C ( 非lucky数个数 ) ( n-i ) ) , ( 0<=i<=这堆数中lucky数总数 ) C求组合数
那么现在的关键是求C ( a, b) 了..有题目数据可知...a,b都可能达到10^5...如果用传统的递推: C( i , j )=C( i-1 , j )+C( i-1 , j-1 ) 是会爆空间+爆时间的...
要求C ( a, b )只能用数学知识了...
C( a, b ) = a! / (b!*(a-b)!) 可以先把n!打个表出来.所有的阶乘就可以直接的取...问题进一步简化为求 ( a / b ) % 1000000007
如果a,b分别取模计算..是错误的...只能 a * (b的逆元) % 1000000007
这里所说的b你逆元,实质上是在模1000000007系统中b的逆元..也就是(b*x)%1000000007=1
问题再简化...求b的逆元....两种思路...
1、费马小定理
根据费马小定理 ( a^(p-1) ) % p = 1 当p是质数并且a不是p的倍数....而题目给的1000000007就是一个质数..所以对于任意一个非p倍数的数有
( a * (a^(p-2) ) % p =1 ..所以 a^(p-2) 就是 a的逆元...用快速幂取模求出即可
2、扩展欧几里德
ax+by = gcd(a,b) 扩展欧几里得就是来求满足条件的一组x,y的...
令x为a的逆元...p为要模的数...根据逆元的定义有 ( a*x ) %p=1....可以理解为 a*x - p*y = 1 , 其中y为整数.
又有 gcd (a,p) = 1..那么 a*x - p*y = gcd (a,p) ..这样就成了拓展欧几里得的形式了..求出x即可
总的来说..费马小定理来得方便...但扩展欧几里德的应用范围更广
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#define ll long long
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 1200
using namespace std;
int n,k,temp[100005],m;
ll lucky[MAXN],dp[MAXN][MAXN],factorial[100005];
bool IsLucky(int x)
{
while (x)
{
if (x%10!=4 && x%10!=7) return false;
x/=10;
}
return true;
}
void PreWork()
{
factorial[0]=1;
for (ll i=1;i<=100000;i++) factorial[i]=(factorial[i-1]*i)%oo;
return;
}
void Ex_Gcd(ll a,ll b,ll &x,ll &y)
{
if (b==0)
{
x=1,y=0;
return;
}
Ex_Gcd(b,a%b,x,y);
ll t;
t=x,x=y,y=t-a/b*y;
return;
}
ll C(ll a,ll b)
{
ll x,y;
if (b>a) return 0;
b=(factorial[b]*factorial[a-b])%oo;
a=factorial[a];
Ex_Gcd(b,oo,x,y);
a=(a*x)%oo;
if (a<0) a+=oo;
return a;
}
int main()
{
PreWork();
int i,j,num;
ll ans;
while (~scanf("%d%d",&n,&k))
{
m=0;
for (i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
if (IsLucky(x)) temp[++m]=x;
}
sort(temp+1,temp+1+m);
temp[0]=num=0;
for (i=1;i<=m;i++)
if (temp[i]!=temp[i-1]) lucky[++num]=1;
else lucky[num]++;
memset(dp,0,sizeof(dp));
for (i=0;i<=num;i++) dp[i][0]=1;
for (i=1;i<=num;i++)
for (j=1;j<=i;j++)
dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]*lucky[i])%oo;
ans=0;
for (i=0;i<=min(k,m);i++)
ans=(ans+dp[num][i]*C(n-m,k-i))%oo;
printf("%I64d\n",ans);
}
return 0;
}
CodeForces 146E - Lucky Subsequence DP+扩展欧几里德求逆元的更多相关文章
- HDU 5768Lucky7(多校第四场)容斥+中国剩余定理(扩展欧几里德求逆元的)+快速乘法
地址:http://acm.hdu.edu.cn/showproblem.php?pid=5768 Lucky7 Time Limit: 2000/1000 MS (Java/Others) M ...
- POJ-1061青蛙的约会,扩展欧几里德求逆元!
青蛙的约会 以前不止一次看过这个题,但都没有去补..好吧,现在慢慢来做. 友情提示 ...
- 公钥密码之RSA密码算法扩展欧几里德求逆元!!
扩展欧几里得求逆元 实话说这个算法如果手推的话问题不大,无非就是辗转相除法的逆过程,还有一种就是利用扩展欧几里德算法,学信安数学基础的时候问题不大,但现在几乎都忘了,刷题的时候也是用kuangbin博 ...
- CodeForces 146E Lucky Subsequence(组合数+DP)
题目描述 Petya loves lucky numbers very much. Everybody knows that lucky numbers are positive integers w ...
- 51Nod 3的幂的和(扩展欧几里德求逆元)
求:3^0 + 3^1 +...+ 3^(N) mod 1000000007 Input 输入一个数N(0 <= N <= 10^9) Output 输出:计算结果 Input示例 3 O ...
- codeforces 492E. Vanya and Field(exgcd求逆元)
题目链接:codeforces 492e vanya and field 留个扩展gcd求逆元的板子. 设i,j为每颗苹果树的位置,因为gcd(n,dx) = 1,gcd(n,dy) = 1,所以当走 ...
- 【hdu 1576】A/B(数论--拓展欧几里德 求逆元 模版题)
题意:给出 A%9973 和 B,求(A/B)%9973的值. 解法:拓展欧几里德求逆元.由于同余的性质只有在 * 和 + 的情况下一直成立,我们要把 /B 转化为 *B-1,也就是求逆元. 对于 B ...
- 扩展gcd求逆元
当模数为素数时可以用费马小定理求逆元. 模数为合数时,费马小定理大部分情况下失效,此时,只有与模数互质的数才有逆元(满足费马小定理的合数叫伪素数,讨论这个问题就需要新开一个博客了). (对于一个数n, ...
- One Person Game(扩展欧几里德求最小步数)
One Person Game Time Limit: 2 Seconds Memory Limit: 65536 KB There is an interesting and simple ...
随机推荐
- spring aop pointcut 切入点是类的公共方法(私有方法不行),还是接口的方法
spring aop pointcut 切入点是类的公共方法(私有方法不行),还是接口的方法 类的公共方法可以,但是私有方法不行 测试一下接口的方法是否能够捕捉到
- KMP算法总结
kmp算法的T子字符串的下标的变化规律 大话数据结构这边书中的KMP算法的讲解跟最终的算法代码还是有很大的差别 java语言只会if判断语句,循环语句,但是这些语句以及可以包罗万象了,可以适用很多情况 ...
- Oracle 创建分页存储过程(转帖)
原贴地址:http://19880614.blog.51cto.com/4202939/1316560 ps:源代码还有很多错误,我修改了 ------------------------------ ...
- MySQL DELETE
MySQL DELETE 语句 你可以使用 SQL 的 DELETE FROM 命令来删除 MySQL 数据表中的记录. 你可以在mysql>命令提示符或PHP脚本中执行该命令. 语法 以下是S ...
- 【windows开发实现记事本程序——逻辑篇1】
1. 主要内容 从本节开始介绍windows开发实现记事本程序的逻辑实现部分.本节的主要内容有以下3点: 1. 主窗口定义 -- 主要介绍记事本主界面窗口对应的窗口类及实现方案 2. RichEdi ...
- 挂载NTFS
1.安装ntfs-3g wget https://tuxera.com/opensource/ntfs-3g_ntfsprogs-2015.3.14.tgz --no-check-certificat ...
- Apache下PHP的几种工作方式
PHP在Apache中一共有三种工作方式:CGI模式.Apache模块DLL.FastCGI模式. 一.CGI模式 PHP 在 Apache 2中的 CGI模式.编辑Apache 配置文件httpd. ...
- Delphi Keycode
Keycode表 字母和数字键的键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码 A 65 J 74 S 83 1 49 B 66 K 75 T 84 2 50 C 67 L ...
- python之7-2类的继承与多态
类的继承的意思就如同父子关系一样,这个儿子继承了父亲的一切,但是在某些地方(属性)相同的时候,儿子的属性大于老子的属性(覆盖),最底层类,总会继承最接近它的那个类的属性init 类的多态总是和继承相连 ...
- codevs 1198 国王游戏
传送门 题目描述 Description 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n位 ...