HDU4828(2014百度之星初赛)求乘法逆元&&Catalan数
来源:互联网 发布:多张图像拼接算法综述 编辑:程序博客网 时间:2024/06/08 22:49
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4828
Catalan 数:前几项为 : 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, ...
原理:
令h(0)=1,h(1)=1,catalan数满足递推式[1]:
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)
例如:h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
另类递推式[2]:
h(n)=h(n-1)*(4*n-2)/(n+1);
递推关系的解为:
h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
递推关系的另类解为:
h(n)=c(2n,n)-c(2n,n+1)(n=0,1,2,...)
逆元 即 逆元素 。
在数学里,逆元素广义化了加法中的加法逆元和乘法中的倒数。直观地说,它是一个可以取消另一给定元素运算的元素。
扩展的欧几里德算法求乘法逆元
扩展欧几里得的应用:
模P乘法逆元
对于整数a、p,如果存在整数b,满足ab mod p =1,则说,b是a的模p乘法逆元。
定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1
证明:
首先证明充分性
如果gcd(a,p) = 1,根据欧拉定理,aφ(p) ≡ 1 mod p,因此
显然aφ(p)-1 mod p是a的模p乘法逆元。
再证明必要性
假设存在a模p的乘法逆元为b
ab ≡ 1 mod p
则ab = kp +1 ,所以1 = ab - kp
因为gcd(a,p) = d
所以d | 1
所以d只能为1
扩展欧几里德算法对于最大公约数的计算和普通欧几里德算法是一致的。计算乘法逆元则显得很难明白。下面是证明:
首先重复拙作整除中的一个论断:
如果gcd(a,b)=d,则存在m,n,使得d = ma + nb,称呼这种关系为a、b组合整数d,m,n称为组合系数。当d=1时,有 ma + nb = 1 ,此时可以看出m是a模b的乘法逆元,n是b模a的乘法逆元。
(按照上面算出来的m,n可能为负数,最后要把它转化为正数)。完整程序如下:*/
#include <iostream>using namespace std;int extended_gcd(int a,int b, int &x, int &y){ if (b == 0) { x = 1; y = 0; return a; } else { int gcd = extended_gcd(b, a % b, x, y); int t = x; x = y; y = t - (a / b) * y; return gcd; }}int main(){ int i, x, y; const int P = 13; for (i = 1; i < P; ++i) { extended_gcd(i, P, x, y); while (x < 0) x += P; printf("1 div %d = %d\n", i, x); } return 0;}//扩展的欧几里德算法求乘法逆元#include <stdio.h>int ExtendedEuclid(int f, int d, int *result);int main() { int x, y, z; z = 0; printf("输入两个数:\n"); scanf("%d%d", &x, &y); if (ExtendedEuclid(x, y, &z)) printf("%d和%d互素,乘法的逆元是:%d\n", x, y, z); else printf("%d和%d不互素,最大公约数为:%d\n", x, y, z); return 0;}int ExtendedEuclid(int f, int d, int *result) { int x1, x2, x3, y1, y2, y3, t1, t2, t3, q; x1 = y2 = 1; x2 = y1 = 0; x3 = (f >= d) ? f : d; y3 = (f >= d) ? d : f; while (1) { if (y3 == 0) { *result = x3; /* 两个数不互素则result为两个数的最大公约数,此时返回值为零 */ return 0; } if (y3 == 1) { *result = y2; /* 两个数互素则resutl为其乘法逆元,此时返回值为1 */ return 1; } q = x3 / y3; t1 = x1 - q*y1; t2 = x2 - q*y2; t3 = x3 - q*y3; x1 = y1; x2 = y2; x3 = y3; y1 = t1; y2 = t2; y3 = t3; }}
打表得到前几项 判断为Catalan 数 但是求Catalan数的过程中有除法 需要求逆元
#include <cstdio>#include <cstring>#include <algorithm>#define MAX 1000003#define MOD 1000000007#define LL long longusing namespace std; LL s[MAX];LL exgcd(LL a,LL b,LL &x,LL &y){ if(b==0){ x=1; y=0; return a; } LL d = exgcd(b,a%b,x,y); LL t=x; x=y; y=t-a/b*y; return d;} void deal(){ s[1]=s[2]=1; int n = MAX; LL x,y; for(int i=2;i<=n;i++){ s[i+1]=(4*i-6)%MOD; s[i+1]=(s[i+1]*s[i])%MOD; exgcd(i,MOD,x,y); s[i+1]=(s[i+1]*((x+MOD)%MOD))%MOD; }} int main(){ int t,n; deal(); scanf("%d",&t); for(int z=1;z<=t;z++){ scanf("%d",&n); printf("Case #%d:\n",z); printf("%I64d\n",s[n+2]); } return 0;}
代码如下
1 0
- HDU4828(2014百度之星初赛)求乘法逆元&&Catalan数
- HDU4828 Grids 2014年百度之星程序设计大赛 - 初赛(第一轮) Catalan数
- HDU4828 Grids 2014百度之星初赛题解
- HDU4828 Grids 百度之星初赛1002解题报告
- 2014百度之星初赛第一轮 HDU 4828 - Grids (卡特兰数 逆元)
- hdu4828(卡特兰数+逆元)
- 百度之星 初赛2 瞬间转移 HDU 5698 (组合数+逆元)
- HDU4828 卡特兰数+逆元
- 卡特兰数+逆元-HDU4828
- 【快速幂+组合数+逆元】HDU5698瞬间移动【2016"百度之星" - 初赛(Astar Round2B)】
- 洛谷[luogu] P1641 [SCOI2010]生成字符串(Catalan数(折线原理)+乘法逆元)
- 2017百度之星初赛(A)1001 小C的倍数问题(求因子数)
- HDU5247找连续数(百度之星初赛)
- 求乘法逆元
- 求乘法逆元
- 求乘法逆元
- 求乘法逆元
- 求乘法逆元
- 分层分类
- 在Xcode中使用Git进行源码版本控制
- Qt之QTableWidget的使用及常用设置
- TinyOS学习 - 射频层析成像之获取RSSI值
- C++构造函数、拷贝构造函数、赋值运算符漫谈(三)——NRV
- HDU4828(2014百度之星初赛)求乘法逆元&&Catalan数
- ubuntu12.04安装php+apache+mysql并安装laravel-4.x
- Object-c中 函数前面的 加号 减号
- 递归算法--2的幂
- Android:广播机制
- 政府采购禁用windows8计算机国产化迎来巨大商机
- C++构造函数、拷贝构造函数、赋值运算符漫谈(二)——函数返回值
- OpenSSLX509证书操作函数
- 黑马程序员_java的IO流三_15