[洛谷P1313]计算系数

本文介绍了一种使用扩展欧几里得算法计算模意义下的组合数的方法,并提供了完整的C++代码实现。通过该方法可以有效地解决一些数论问题。

题目←

在wwq大佬博客发现的,将数论知识点总结的很好的题
也可以用杨辉三角求组合数,不过就跟着大佬练扩欧吧……

#include<iostream>
#include<cstdio>
#include<algorithm>
#define LL long long
#define P 10007
using namespace std;
const int MAXN = 20000 + 50;
LL x,y;
void exgcd(LL a,LL b){
    if(!b){
        x = 1;
        y = 0;
        return;
    }
    exgcd(b,a%b);
    LL tmp = y;
    y = x - (a/b)*y;
    x = tmp;
}
LL a,b,k,n,m,ny,xs;
LL fast_pow(LL n,LL k){
    if(!k)return 1;
    LL tmp = fast_pow(n,k >> 1)%P;
    if(k & 1){
        return (tmp*tmp*(n%P))%P;
    }
    else return (tmp*tmp)%P;
}
int main(){
    cin >> a >> b >> k >> n >> m;
    LL tmp = 1;
    for(int i = 1;i <= m;i ++){
        tmp = (tmp*i)%P;
    }
    for(int i = 1;i <= k - m;i ++){
        tmp = (tmp*i)%P;
    }
    exgcd(tmp,P);
    x = (x%P + P)%P;
    tmp = 1;
    for(int i = 1;i <= k;i ++){
        tmp = (tmp*i)%P;
    }
    xs = (x*tmp)%P;
    xs = (((fast_pow(a,n)*fast_pow(b,m))%P)*xs)%P;
    cout << xs;
}
<think>根据提供的引用,我们可以找到引用[5]中提到了洛谷P5732(杨辉三角)的C语言代码。用户现在需要查找洛谷P5732题目的C语言答案。 引用[5]中给出的代码是一个生成杨辉三角的C语言程序,但是注意,该代码存在一些问题和改进空间。例如: 1. 它使用了一个固定大小的二维数组(30x30),但题目要求是输入一个整数n(1<=n<=20),所以数组大小可以定义为[21][21]或[22][22](如果从1开始索引,可能需要21行,因为n最大为20)但这里题目要求n<=20,所以30是足够的。 2. 代码中第一行的处理使用了break,这样在输出第一行后就会跳出内层循环,但这样写循环结构稍显复杂。 3. 输出格式:题目要求每个数字之间用空格隔开,并且每行最后一个数字后面没有多余空格。但上述代码在每个数字后都输出一个空格,包括最后一个,这样每行末尾会多一个空格,但题目通常允许行末空格(或要求不严格),不过最好检查一下。 然而,引用[5]提供的代码并不完整(缺少一些边界处理)且可能有误。例如,在内层循环中,当i=1且j=1时,输出后break,这样第一行就只有一个元素。但随后的行呢?在内层循环中,当i>=2时,会计算arr[i][j]=arr[i-1][j-1]+arr[i-1][j]。注意,对于每一行的第一个元素(j=1),arr[i-1][j-1]即arr[i-1][0],而我们的数组从1开始索引,所以arr[i-1][0]实际上是0(因为初始化为0),这样每一行的第一个元素就是arr[i-1][0](0)+arr[i-1][1](上一行的第一个元素),所以第一行的元素设置成了1,后面每一行的第一个元素也会是1。同样,每一行的最后一个元素(j=i)会用到arr[i-1][i-1]和arr[i-1][i](其中arr[i-1][i]也是0,因为初始化为0),所以最后一列也是1。 但是,该代码在输出第一行时,输出后break,跳出了内层循环,然后输出换行。所以第一行输出正确。但是,对于后续行,内层循环从j=1到j=i,每次输出一个数字和一个空格,然后换行。 然而,这个代码在初始化数组时,将数组所有元素初始化为0,然后从第1行第1列开始(索引从1开始)填充。但是数组定义是arr[30][30],而循环中i和j都从1开始,所以不会用到0索引,这样边界处理是安全的。 但是,我们注意到当n=1时,输出第一行(1)后程序会输出换行,没有问题。当n>=2时,第二行开始,内层循环不会进入if(i==1&&j==1)的条件,所以会正常计算。 然而,这个代码在输出时,每行最后一个数字后面也有一个空格。虽然题目没有严格要求去掉行末空格,但通常来说,行末空格在OJ中是可以接受的,因为很多OJ会自动忽略行末空格和文末换行。但为了更符合要求,我们可以调整输出,去掉每行最后一个空格。 但是,引用[5]提供的代码并没有去掉行末空格。因此,我们可以提供一个改进版本。 另外,注意引用[5]中代码的数组初始化:int arr[30][30]={0}; 这样可以确保所有元素为0,然后从[1][1]开始使用,所以边界元素(比如每一行的第一个和最后一个)都能正确计算。 不过,我们也可以使用更标准的写法,即循环从0开始索引,但题目要求从第一行开始输出。这里我们按照引用[5]的写法,使用1-indexed。 考虑到用户需要的是洛谷P5732的C语言答案,我们可以参考引用[5]的代码并改进其输出格式(去掉行末空格)。 改进思路: 在每一行中,当j<i时,输出数字后加一个空格;当j==i时,只输出数字,不加空格。这样就能避免行末空格。 另外,我们可以将数组大小改为动态的(根据输入的n),但题目要求n<=20,所以固定大小30是足够的。 修改后的代码: ```c #include <stdio.h> int main() { int n; scanf("%d", &n); int arr[30][30] = {0}; // 初始化数组为0 // 生成杨辉三角 for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { // 每一行的第一个和最后一个元素应该是1 if (j == 1 || j == i) { arr[i][j] = 1; } else { // 其他情况等于上一行的j-1和j位置的和 arr[i][j] = arr[i-1][j-1] + arr[i-1][j]; } // 输出当前数字,如果是该行最后一个数字则不输出空格,否则输出空格 if (j == i) { printf("%d", arr[i][j]); } else { printf("%d ", arr[i][j]); } } printf("\n"); // 每行结束换行 } return 0; } ``` 上述代码中,我们显式地设置了每一行的第一个和最后一个元素为1,然后中间的元素由上一行的相邻两个元素相加得到。这样逻辑更清晰。 但是,原引用[5]中的代码在第一行处理时用了break,而我们这里用条件判断每一行的第一个和最后一个,这样更通用。 注意:题目要求输出n行,第i行有i个数,并且每个数之间用空格隔开。我们的代码符合这一要求。 我们也可以不显式判断第一个和最后一个,而是通过初始化边界条件来实现。但上述代码已经足够清晰。 因此,我们可以将上述代码作为洛谷P5732的答案。 但是,我们还需要注意题目要求:输入一个整数n(1<=n<=20),输出n行对应的杨辉三角。 我们测试一下n=5的情况: 输入5,输出: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 符合要求。 所以,我们给出以下答案: </think>根据引用[5],洛谷P5732题目是关于生成杨辉三角的。以下是C语言实现的代码及解析: ### 洛谷P5732 C语言代码 ```c #include <stdio.h> int main() { int n; scanf("%d", &n); // 输入杨辉三角的行数 int arr[30][30] = {0}; // 初始化二维数组(最大支持30×30) for (int i = 1; i <= n; i++) { // 控制行数 for (int j = 1; j <= i; j++) { // 控制每行的元素个数 if (j == 1 || j == i) { arr[i][j] = 1; // 每行首尾元素赋值为1 } else { // 中间元素 = 上一行左上方元素 + 上一行正上方元素 arr[i][j] = arr[i-1][j-1] + arr[i-1][j]; } printf("%d ", arr[i][j]); // 输出当前元素 } printf("\n"); // 每行结束换行 } return 0; } ``` ### 代码解析 1. **核心逻辑**: - 杨辉三角第 $i$ 行有 $i$ 个元素。 - 每行首尾元素恒为 $1$(`if (j == 1 || j == i)`)。 - 其余元素满足递推关系: $$ \text{arr}[i][j] = \text{arr}[i-1][j-1] + \text{arr}[i-1][j] $$ 2. **示例输出**(输入 `n=5`): ``` 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 ``` 3. **注意事项**: - 数组大小 `arr[30][30]` 满足题目要求 $n \leq 20$。 - 初始化 `{0}` 确保未赋值元素为 $0$(避免计算错误)。 ### 改进建议 若需严格符合题目输出格式(行末无空格),可调整输出部分: ```c for (int j = 1; j <= i; j++) { // ... 计算逻辑同上 printf("%d", arr[i][j]); if (j < i) printf(" "); // 非末尾元素才输出空格 } ``` ### 相关问题 1. 如何优化杨辉三角的内存使用(例如用一维数组实现)? 2. 杨辉三角有哪些数学性质(如二项式系数、斐波那契数列联系)? 3. 如何输出杨辉三角的直角对称形式? [^1]: 洛谷题单分支结构 [^2]: 洛谷B2005字符图形 [^3]: 洛谷P1161开灯问题 [^4]: 洛谷P1601高精度加法 [^5]: 洛谷P5732杨辉三角
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值