其实思维难度不是很大,但是各种处理很麻烦,公式推导到最后就是一个bsgs算法解方程

  1. /*
  2. 要给M行N列的网格染色,其中有B个不用染色,其他每个格子涂一种颜色,同一列上下两个格子不能染相同的颜色
  3. 涂色方案%100000007的结果是R,现在给出R,N,K,请求出最小的M
  4. 对于第一行来说,每个位置有k种选择,那么填色方案数是k^n
  5. 对于第二行来说,每个位置有k-1中选择,那么填色方案数时(k-1)^n种
  6. 依次类推,如果i+1行的某个格子上面是白格,那么这个格子有k种填色方案
  7.  
  8. 将M行分为两部分,第一部分是固定的,即行数最大的B向下一行,注意特判情况
  9. 第二部分是不固定的,即不停增加行数M,直到求出结果=R
  10.  
  11. 另P=(K-1)^N,所以方案总数是cnt*P^M=R (mod 100000007)
  12. P^M = cnt^-1 * R(mod 100000007)
  13. 逆元算一下即可
  14. 用bsgs算法 解出这个关于M的方程即可
  15. */
  16. #include<bits/stdc++.h>
  17. using namespace std;
  18. #define ll long long
  19. #define maxn 510
  20. #define mod 100000007
  21.  
  22. int n,m,k,b,r,x[maxn],y[maxn];
  23. set<pair<int,int> >best;
  24.  
  25. ll pow_mod(ll a,ll p){//快速幂
  26. ll res=;
  27. while(p){
  28. if(p%)
  29. res=res*a%mod;
  30. p>>=;
  31. a=a*a%mod;
  32. }
  33. return res;
  34. }
  35. ll exgcd(ll a,ll b,ll &x,ll &y){
  36. if(b==){x=;y=;return a;}
  37. ll d=exgcd(b,a%b,y,x);
  38. y-=a/b*x;
  39. return d;
  40. }
  41. ll inv(ll a){//ax+y*mod=1 ==> ax=1(mod mod),所以x就是a关于mod的逆元
  42. ll d,x,y;
  43. d=exgcd(a,mod,x,y);
  44. return d==?(x+mod)%mod:-;
  45. }
  46. int log_mod(int a,int b){//bsgs算法,求解a^x=b(mod m)方程
  47. int m, v, e = , i;
  48. m = (int)sqrt(mod+0.5);
  49. v = inv(pow_mod(a, m));
  50. map<int, int> x;
  51. x[] = ;
  52.  
  53. for(int j=;j<m;j++){//建立hash表,x=i*m+j
  54. e=(ll)e*a%mod;
  55. if(!x.count(e))
  56. x[e]=j;
  57. }
  58. for(int i=;i<m;i++){
  59. if(x.count(b))
  60. return i*m+x[b];
  61. b=(ll)b*v%mod;//这里实际上是用逆元处理了,即将a^(i*m+j)=b (mod m)转化为a^j=b^(i*m)^(-1) (mod m)
  62. }
  63. return -;
  64. }
  65. int count(){//计算固定部分的方案数
  66. int c=;//统计b块下面的的方格
  67. for(int i=;i<b;i++)
  68. if(x[i]!=m && !best.count(make_pair(x[i]+,y[i])))
  69. c++;
  70. c+=n;
  71. for(int i=;i<b;i++)
  72. if(x[i]==)
  73. c--;
  74.  
  75. return pow_mod(k-,(ll)m*n-b-c)*pow_mod(k,c)%mod;
  76. }
  77. int doit(){
  78. int cnt=count();//先求出第一部分的cnt
  79. if(cnt==r)
  80. return m;
  81.  
  82. int c=;//要把第m+1行单独拿出来考虑
  83. for(int i=;i<b;i++)
  84. if(x[i]==m)
  85. c++;
  86. m++;
  87. cnt=cnt*pow_mod(k,c)%mod;
  88. cnt=cnt*pow_mod(k-,n-c)%mod;
  89. if(cnt==r)
  90. return m;
  91.  
  92. //接下去就只要求对数方程即可
  93. int P=pow_mod(k-,n);
  94. return log_mod(P,r*inv(cnt)%mod)+m;
  95. }
  96. int main(){
  97. int t,cas=;
  98. scanf("%d",&t);
  99. while(t--){
  100. scanf("%d%d%d%d",&n,&k,&b,&r);
  101. best.clear();
  102. m=;
  103. for(int i=;i<b;i++){
  104. scanf("%d%d",&x[i],&y[i]);
  105. m=max(x[i],m);
  106. best.insert(make_pair(x[i],y[i]));
  107. }
  108. printf("Case %d: %d\n",cas++,doit());
  109. }
  110. }

uva11916 bsgs算法逆元模板,求逆元,组合计数的更多相关文章

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

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

  2. BSGS算法(模板)

    BSGS (大步小步算法) 已知\(a.b. c\),求\(x\).令\(a^x \equiv b \pmod c\). 步骤 \[m = \lceil \sqrtc\ \rceil \]\[x = ...

  3. 算法竞赛进阶指南0x36组合计数

    概述 AcWing211. 计算系数 #include <bits/stdc++.h> using namespace std; const int mod = 10007 ; int k ...

  4. hdu 1576 求逆元

    题意:给出n=A mod 9973和B,求(A/B) mod 9973 昨天用扩展欧几里得做过这题,其实用逆元也可以做. 逆元的定义:例如a*b≡1 (mod m),则b就是a关于m的逆元. 求逆元方 ...

  5. POJ2417 Discrete Logging | A,C互质的bsgs算法

    题目: 给出A,B,C 求最小的x使得Ax=B  (mod C) 题解: bsgs算法的模板题 bsgs 全称:Baby-step giant-step 把这种问题的规模降低到了sqrt(n)级别 首 ...

  6. Codeforces 451E Devu and Flowers(组合计数)

    题目地址 在WFU(不是大学简称)第二次比赛中做到了这道题.高中阶段参加过数竞的同学手算这样的题简直不能更轻松,只是套一个容斥原理公式就可以.而其实这个过程放到编程语言中来实现也没有那么的复杂,不过为 ...

  7. 多项式求逆元详解+模板 【洛谷P4238】多项式求逆

    概述 多项式求逆元是一个非常重要的知识点,许多多项式操作都需要用到该算法,包括多项式取模,除法,开跟,求ln,求exp,快速幂.用快速傅里叶变换和倍增法可以在$O(n log n)$的时间复杂度下求出 ...

  8. BSGS算法+逆元 POJ 2417 Discrete Logging

    POJ 2417 Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4860   Accept ...

  9. 线性筛prime/phi/miu/求逆元模板

    这绿题贼水...... 原理我不讲了,随便拿张草稿纸推一下就明白了. #include <cstdio> using namespace std; ; int su[N],ans,top; ...

随机推荐

  1. Loadrunner 如何在其他浏览器进行录制(一)

    背景: 由于lr只支持低版本的IE浏览器,当我们想使用高版本或其他浏览器进行录制时,这时,我们需要用到浏览器的代理功能. 传统的访问模式如下: 使用代理后的访问方式: 下面来总结一下具体的步骤: 1. ...

  2. Ajax——从服务器获取各种文件

    ajax.js内容 function ajax(url,fnWin,fnFaild){ //1.创建ajax对象 var xhr = window.XMLHttpRequest ? new XMLHt ...

  3. Microsoft SQL - 数据库管理系统

    数据库管理系统(Server Management Studio) SQL Server Management Studio是一个数据库管理系统软件,数据库可以看成是一个个存储数据的文件,而Manag ...

  4. 二叉查找树(Binary Search Tree)

    二叉树的一个重要的应用是他们在查找中的使用. 以下是二叉查找树的查找代码 #include <stdio.h> int main() { typedef struct Node{ int ...

  5. mysql数据库可以远程连接或者说用IP地址可以访问

    mysql数据库可以远程连接或者说用IP地址可以访问 一般情况不建议直接修改root的权限, 先看下,自己mysql数据库的用户级权限 mysql -u root -p----->用root登陆 ...

  6. java高级 - java利用listener实现回调,即观察者模式

    https://blog.csdn.net/lin_sir6/article/details/70052954

  7. Graham 扫描法找凸包(convexHull)

    凸包定义 通俗的话来解释凸包:给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点  Graham扫描法 由最底的一点 \(p_1\) 开始(如果有多个这样的点, ...

  8. MySQL DROP TABLE操作以及 DROP 大表时的注意事项【转】

    删表 DROP TABLE Syntax DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name] ... [RESTRICT | CASCAD ...

  9. Python3学习笔记32-xlwt模块

    xlwt模块是用来写入excel的第三方模块,需要下载安装后才能使用. 设置字体样式 import xlwt #初始化一个excel excel = xlwt.Workbook(encoding='u ...

  10. localtime函数和strftime函数

    localtime函数 功能: 把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间,而gmtime函数转换后的时间没有经过时区变换,是UTC时间 . 用法: #include & ...