题意:

一个数只含有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:

  1. #include<iostream>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<cmath>
  5. #include<queue>
  6. #include<stack>
  7. #include<set>
  8. #include<algorithm>
  9. #define ll long long
  10. #define oo 1000000007
  11. #define pi acos(-1.0)
  12. #define MAXN 1200
  13. using namespace std;
  14. int n,k,temp[100005],m;
  15. ll lucky[MAXN],dp[MAXN][MAXN],factorial[100005];
  16. bool IsLucky(int x)
  17. {
  18. while (x)
  19. {
  20. if (x%10!=4 && x%10!=7) return false;
  21. x/=10;
  22. }
  23. return true;
  24. }
  25. void PreWork()
  26. {
  27. factorial[0]=1;
  28. for (ll i=1;i<=100000;i++) factorial[i]=(factorial[i-1]*i)%oo;
  29. return;
  30. }
  31. void Ex_Gcd(ll a,ll b,ll &x,ll &y)
  32. {
  33. if (b==0)
  34. {
  35. x=1,y=0;
  36. return;
  37. }
  38. Ex_Gcd(b,a%b,x,y);
  39. ll t;
  40. t=x,x=y,y=t-a/b*y;
  41. return;
  42. }
  43. ll C(ll a,ll b)
  44. {
  45. ll x,y;
  46. if (b>a) return 0;
  47. b=(factorial[b]*factorial[a-b])%oo;
  48. a=factorial[a];
  49. Ex_Gcd(b,oo,x,y);
  50. a=(a*x)%oo;
  51. if (a<0) a+=oo;
  52. return a;
  53. }
  54. int main()
  55. {
  56. PreWork();
  57. int i,j,num;
  58. ll ans;
  59. while (~scanf("%d%d",&n,&k))
  60. {
  61. m=0;
  62. for (i=1;i<=n;i++)
  63. {
  64. int x;
  65. scanf("%d",&x);
  66. if (IsLucky(x)) temp[++m]=x;
  67. }
  68. sort(temp+1,temp+1+m);
  69. temp[0]=num=0;
  70. for (i=1;i<=m;i++)
  71. if (temp[i]!=temp[i-1]) lucky[++num]=1;
  72. else lucky[num]++;
  73. memset(dp,0,sizeof(dp));
  74. for (i=0;i<=num;i++) dp[i][0]=1;
  75. for (i=1;i<=num;i++)
  76. for (j=1;j<=i;j++)
  77. dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]*lucky[i])%oo;
  78. ans=0;
  79. for (i=0;i<=min(k,m);i++)
  80. ans=(ans+dp[num][i]*C(n-m,k-i))%oo;
  81. printf("%I64d\n",ans);
  82. }
  83. return 0;
  84. }

CodeForces 146E - Lucky Subsequence DP+扩展欧几里德求逆元的更多相关文章

  1. HDU 5768Lucky7(多校第四场)容斥+中国剩余定理(扩展欧几里德求逆元的)+快速乘法

    地址:http://acm.hdu.edu.cn/showproblem.php?pid=5768 Lucky7 Time Limit: 2000/1000 MS (Java/Others)    M ...

  2. POJ-1061青蛙的约会,扩展欧几里德求逆元!

                                                               青蛙的约会 以前不止一次看过这个题,但都没有去补..好吧,现在慢慢来做. 友情提示 ...

  3. 公钥密码之RSA密码算法扩展欧几里德求逆元!!

    扩展欧几里得求逆元 实话说这个算法如果手推的话问题不大,无非就是辗转相除法的逆过程,还有一种就是利用扩展欧几里德算法,学信安数学基础的时候问题不大,但现在几乎都忘了,刷题的时候也是用kuangbin博 ...

  4. CodeForces 146E Lucky Subsequence(组合数+DP)

    题目描述 Petya loves lucky numbers very much. Everybody knows that lucky numbers are positive integers w ...

  5. 51Nod 3的幂的和(扩展欧几里德求逆元)

    求:3^0 + 3^1 +...+ 3^(N) mod 1000000007 Input 输入一个数N(0 <= N <= 10^9) Output 输出:计算结果 Input示例 3 O ...

  6. codeforces 492E. Vanya and Field(exgcd求逆元)

    题目链接:codeforces 492e vanya and field 留个扩展gcd求逆元的板子. 设i,j为每颗苹果树的位置,因为gcd(n,dx) = 1,gcd(n,dy) = 1,所以当走 ...

  7. 【hdu 1576】A/B(数论--拓展欧几里德 求逆元 模版题)

    题意:给出 A%9973 和 B,求(A/B)%9973的值. 解法:拓展欧几里德求逆元.由于同余的性质只有在 * 和 + 的情况下一直成立,我们要把 /B 转化为 *B-1,也就是求逆元. 对于 B ...

  8. 扩展gcd求逆元

    当模数为素数时可以用费马小定理求逆元. 模数为合数时,费马小定理大部分情况下失效,此时,只有与模数互质的数才有逆元(满足费马小定理的合数叫伪素数,讨论这个问题就需要新开一个博客了). (对于一个数n, ...

  9. One Person Game(扩展欧几里德求最小步数)

    One Person Game Time Limit: 2 Seconds      Memory Limit: 65536 KB There is an interesting and simple ...

随机推荐

  1. asp.net中Page.ClientScript.RegisterStartupScript用法小结(转)

    //ASP.NET后台页面跳转 Page.ClientScript.RegisterStartupScript(Page.GetType(), "", "<scri ...

  2. underscorejs-groupBy学习

    2.18 groupBy 2.18.1 语法 _.groupBy(list, iteratee, [context]) 2.18.2 说明 把list分为多个集合,iterator为分组的依据,返回值 ...

  3. javascript Array类型 方法大全

    1,创建数组 //第一种是使用Array构造函数 var colors = new Array(); var colors = new Array(20); //创建length为20的数组 var ...

  4. mysql的sql优化案例

    前言 mysql的sql优化器比较弱,选择执行计划貌似很随机. 案例 一.表结构说明mysql> show create table table_order\G***************** ...

  5. mysql存储过程的权限 definer

    mysql中用户对存储过程的权限有: ALTER ROUTINE 编辑或删除存储过程 CREATE ROUTINE 创建存储过程 EXECUTE运行存储过程 存储过程的创建者拥有存储过程的ALTER. ...

  6. 驱动读写进程内存R3,R0通信

    stdafx.h 头文件代码 #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. #defin ...

  7. Permission denied (publickey).

    问题: ssh-keygen -t rsa -C "youremail@example.com" 若是接连按三次回车,会在-/.ssh下生成 id_rsa, id_rsa.pub ...

  8. SpringMVC入门1

    SpringMVC核心类与接口 •DispatcherServlet 前端控制器(也称总控制器),把请求给转发到具体的控制类 •HandlerMapping 映射处理器,负责映射中央处理器转发给con ...

  9. mapreduce (二) MapReduce实现倒排索引(一) combiner是把同一个机器上的多个map的结果先聚合一次

    1 思路:0.txt MapReduce is simple1.txt MapReduce is powerfull is simple2.txt Hello MapReduce bye MapRed ...

  10. org.elasticsearch.bootstrap : JNA not found. native methods will be disabled

    在pom.xml中添加以下依赖,解决elasticsearch的WARN: <dependency> <groupId>com.sun.jna</groupId> ...