2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

题目链接

分析:打表以后就能发现时卡特兰数, 但是有除法取余。

f[i] = f[i-1]*(4*i - 2)/(i+1);

看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展gcd, 不是用逆元吗。。

网上还有别人的解释,没看懂,贴一下:

(a / b) % m = ( a %
(m*b)) / b

笔者注:鉴于ACM题目特别喜欢M=1000000007,为质数:

当gcd(b,m) = 1, 有性质:
(a/b)%m = (a*b^-1)%m, 其中b^-1是b模m的逆元.

求出b相对于m的逆元b^(-1),即b*(b^(-1)) = 1
(mod m)。有b*b^(-1) - km = 1,其中k是一整数. 用Extended Euclid算法可以求出`b^(-1)。然后计算a*b^(-1)
mod m = ( (a%m) * (b^(-1)%m ) % m; 其值与(a/b) mod m相同

推导:a/b = x (mod m)
--两边同乘一个数--> a = bx (mod m) ---x=b^-1a-> a = (b^-1) ba (mod m)

再利用b^-1*b = 1(mod m) .
所以可以得出 x = b^-1*a是成立的。

所以
(a/b) mod m 的解与 (a*b^-1)%m的解是一样的。 而后着可以利用模对乘法的线性性

AC代码:


 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <algorithm>
6 #define LL __int64
7 using namespace std;
8 const int mo = 1000000000 + 7;
9 const int maxn = 1000000 + 10;
10 LL f[maxn];
11
12 LL exgcd(LL a,LL b,LL &x,LL &y)
13 {
14 if(b==0)
15 {
16 x=1; y=0; return a;
17 }
18 LL d = exgcd(b,a%b,x,y);
19 LL t=x;
20 x=y;
21 y=t-a/b*y;
22 return d;
23 }
24 void init()
25 {
26 int i;
27 LL x, y;
28 f[0] = f[1] = 1;
29 for(i = 2; i < maxn-5; i++)
30 {
31 f[i] = f[i-1]*(4*i-2)%mo;
32 exgcd(i+1, mo, x, y);
33 f[i] = (f[i]*((x+mo)%mo))%mo;
34 }
35 }
36 int main()
37 {
38 int t, n, ca = 1;
39 init();
40 scanf("%d", &t);
41 while(t--)
42 {
43 scanf("%d", &n);
44 printf("Case #%d:\n", ca++);
45 printf("%I64d\n", f[n]);
46 }
47 return 0;
48 }

扩展gcd:


 1 //扩展 GCD
2 //求x, y使得gcd(a, b) = a * x + b * y;
3
4 int extgcd(int a, int b, int & x, int & y)
5 {
6 if (b == 0) { x=1; y=0; return a; }
7 int d = extgcd(b, a % b, x, y);
8 int t = x; x = y; y = t - a / b * y;
9 return d;
10 }

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余
扩展gcd),布布扣,bubuko.com

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余
扩展gcd)

时间: 2024-12-26 16:10:19

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)的相关文章

2014年百度之星程序设计大赛 - 初赛(第二轮)

1001 暴力 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 100100; int ll[maxn], rr[maxn]; struct node { int x, y, bj; }e[maxn]; int main() { int cas = 1; int T; scanf("%d", &T);

2014年百度之星程序设计大赛 - 初赛(第二轮)Chess

题目描述:小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘上的走法遵循十字路线.也就是说,如果"王"当前在(x,y)点,小度在下一步可以移动到(x+1, y), (x-1, y), (x, y+1), (x, y-1), (x+2, y), (x-2, y), (x, y+2), (x, y-2) 这八个点中的任意一个. 小度觉得每次都是小良赢,没意思.为了难倒小良,他想出

2014年百度之星程序设计大赛 资格赛第一题 (longlong)

解题思路: 只要看(A-V)*K 这个公式的更新值是否大于等于A ,大于的话继续循环,否则报错 注意一点,数据会爆int WA代码: #include<stdio.h> int main(){ long long n ,m, v, k; int t; scanf("%d",&t); while(t--){ scanf("%lld%lld%lld%lld",&n,&m,&v,&k); int cnt = 0; whi

2014年百度之星程序设计大赛 - 资格赛 第一题 Energy Conversion

Problem Description   魔法师百小度也有遇到难题的时候-- 现在,百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这种魔法文字需要耗费大量的能量和大量的脑力. 过了许久,百小度终于读懂魔法文字的含义:石门里面有一个石盘,魔法师需要通过魔法将这个石盘旋转X度,以使上面的刻纹与天相对应,才能打开石门. 但是,旋转石盘需要N点能量值,而为了解读密文,百小度的能量值只剩M点了!破坏石门是不可能的,因为那将需要更多的能量.不过,幸运的是,作为魔法师的百小度可以耗费V点能量

2014年百度之星程序设计大赛 - 资格赛 1002 Disk Schedule(双调欧几里得旅行商问题)

Problem Description 有很多从磁盘读取数据的需求,包括顺序读取.随机读取.为了提高效率,需要人为安排磁盘读取.然而,在现实中,这种做法很复杂.我们考虑一个相对简单的场景.磁盘有许多轨道,每个轨道有许多扇区,用于存储数据.当我们想在特定扇区来读取数据时,磁头需要跳转到特定的轨道.具体扇区进行读取操作.为了简单,我们假设磁头可以在某个轨道顺时针或逆时针匀速旋转,旋转一周的时间是360个单位时间.磁头也可以随意移动到某个轨道进行读取,每跳转到一个相邻轨道的时间为400个单位时间,跳转

2014年百度之星程序设计大赛 - 资格赛 1004 -- Labyrinth

Labyrinth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1453    Accepted Submission(s): 500 Problem Description 度度熊是一只喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫只能从矩阵左上角第一个方格开始走,只有走到右上角的第一个格子才算走出迷宫,每一次只能走一格,

2014年百度之星程序设计大赛 - 资格赛 1001 Energy Conversion

Energy Conversion Problem Description 魔法师百小度也有遇到难题的时候-- 现在,百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这种魔法文字需要耗费大量的能量和大量的脑力. 过了许久,百小度终于读懂魔法文字的含义:石门里面有一个石盘,魔法师需要通过魔法将这个石盘旋转X度,以使上面的刻纹与天相对应,才能打开石门. 但是,旋转石盘需要N点能量值,而为了解读密文,百小度的能量值只剩M点了!破坏石门是不可能的,因为那将需要更多的能量.不过,幸运的是,作

2014年百度之星程序设计大赛 - 资格赛 1004 Labyrinth(Dp)

# -*- coding: utf-8 -*- """ Created on Fri May 16 17:24:05 2014 @author: lifeix """ #快速排序 import sys import random length = 30 def qsort(arr,left,right): lp = left rp = right if lp == rp:return while True: while arr[lp] >=

2017&quot;百度之星&quot;程序设计大赛 - 初赛(A)

2017"百度之星"程序设计大赛 - 初赛(A) hdu6108    求出 n-1 的因子个数即可 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b;