求组合数 (数据范围0 < a < b < 1000000 ,询问 10000)

求组合数

例子

ACwing 886
在这里插入图片描述

思路

题目范围过大,必须预处理 , 仅仅考组合数递归来预处理不够,1e5 * 1e5已经超了 , 故预处理fact[a] , infact[a- b] ,infact[b] (infact 指的是逆元)

代码

using namespace std ;

typedef long long LL;
const int N = 100200, mod = 1e9 +7;
int fact[N] ,infact[N];
//int c[N][N];

int  qpow(int i , int p ,int m)
{
    int res = 1;
    while(p){
        if(p & 1)  res = (LL)res * i % m;
        p >>= 1;
        i = (LL)i * i % mod ; 
    }
    
    return res;
}
void init(){
    fact[0] = infact[0] =1;
    for(int i = 1; i < N ; i ++){
        fact[i] = (LL)fact[i-1] * i % mod ;
        infact[i] = (LL)infact[i-1] * qpow(i , mod-2 , mod) % mod;
        // 根据逆元的特性 求infact[i-1 ]就是在求1 / fact[i-1](模 mod) , 并且根据费马小定理 , 因为mod 为质数 ,1 / i 的逆元 (模 mod )就是 qpow(i , mod-2 , mod) % mod ,利用到快速幂
    }
}

int main(){
    init();
    int n;
    cin >> n;
    while(n--){
        int a ,b;
        cin >> a >>b;
        printf("%d\n" , (LL)fact[a] * infact[a - b] % mod * infact[b] % mod);      
    }
    
    return 0;
}

总结

  • 求组合数需要根据不同的数据范围来选择不同的算法
1. GNU GCC 是常用的 C/C++语言编译器。现需要使用 g++将 luogu.cpp 编译为可执行文件 luogu,可以使用编译命令( )。 A. g++ -S luogu luogu.cpp B. g++ -S luogu.cpp luogu C. g++ -o luogu luogu.cpp D. g++ -o luogu.cpp luogu 2. 关于编译语言与解释语言,以下说法错误的是( )。 A. C++语言是编译语言,需要先经过编译得到可执行程序,才能交由机器执行。 B. 编译语言程序每次执行都需要重新编译。 C. 解释器负责将解释语言的源程序翻译为可以执行的机器代码。 D. Python 是常见的解释语言。 3. 阅读下面的代码,若输入的 x 是 1 至 10 范围内的正整数,输出不可能是( )。 01 02 03 04 05 06 07 08 #include <iostream> using namespace std; int main() { int x; cin >> x; switch(x) { case 1: { cout << "A"; break; } case 3: { cout << "C"; } default: { cout << "Q"; } LUOGU SCP-J 2025 第C++语言试题 第 2 页,共 1009 10 11 12 case 5: { cout << "E"; } } return 0; } A. A B. CQE C. QE D. Q 4. k(k>4)进制数 4321 与十进制数( )相等。 A. 4321 B. 4k4+3k3+2k2+k C. 4k3+3k2+2k+1 D. 10k 5. 阅读以下代码片段。当代码片段执行完毕后,ans 的值为( )。 01 02 03 04 05 06 int N = 10, ans = 0, x = 0; for(int i = 1; i <= N; i++) { for(int j = i + 1; j <= N; j++) { ans += ++x; } } A. 45 B. 55 C. 990 D. 1035 6. 给定个空栈,支持入栈出栈操作。将 1 至 10 依次入栈,第个出栈的数为 8,则第 二个出栈的数不可能为( )。 A. 1 B. 7 C. 9 D. 10 7. 有序表中有 100 个元素,使用二分法查找元素 X。有( )个数可以通过恰好 5 次查找找 到。 A. 100 B. 32 C. 31 D. 16 8. 下面的表格是无向图 G 的邻接矩阵,图 G 中度最大的点的度为( )。 A B C D E A 0 1 1 0 1 B 1 0 1 0 0 C 1 1 0 1 1 D 0 0 1 0 1 E 1 0 1 1 0 LUOGU SCP-J 2025 第C++语言试题 第 3 页,共 10 页 A. 1 B. 2 C. 3 D. 4 9. 8 支队伍均分为第组与第二组进行小组赛。A 队 B 队在同组,而与 C 队不在同组 的分组方案数有( )种。 A. 10 B. 20 C. 30 D. 40 10. 将根长度为 3 的木棍折为三段,当断点的位置在木棍中等概率分布时,三段木棍可以 构成三角形的概率为( )。 A. 1 B. 0.5 C. 0.25 D. 0.125 11. 下列关于快速排序的说法中,不正确的是( )。 A. 快速排序典型地应用了分治法的思想。 B. 快速排序的最坏时间复杂度为 O(n log n)。 C. 快速排序是基于交换的排序。 D. sort 函数是 STL 提供的快排函数,同时结合了堆排序、插入排序等技术。 12. 关于整数的各种 8 位二进制编码方法,说法错误的是( )。 A. -17 的原码为 10010001 B. 22 的补码为 00010110 C. -13 的反码为 11110010 D. 以上说法存在错误 13. 表达式(x-2x-1/2) 4 中,x 的系数为( )。 A. 12 B. -12 C. 24 D. -24 14. 二叉树 T 的中序遍历为 CGEADBF,后序遍历为 GECDFBA,则其前序遍历为( )。 A. ACEGBDF B. ACGEBDF C. ABDFCEG D. ABCDEFG 15. 2024 年,来自谷歌 DeepMind 的米斯·哈萨比斯约翰·江珀获得了( ),以表彰他们 在人工智能方面的贡献。 A. 王选奖 B. 图灵奖 C. 诺贝尔奖 D. 贝尔奖 LUOGU SCP-J 2025 第C++语言试题 第 4 页,共 10 页 二、阅读程序(程序输入不超过数组或字符串定义的范围;判断题正确填 T,错误填 F;除特 殊说明外,判断题 1.5 分,选择题 3 分,共计 40 分) (1) 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 #include <bits/stdc++.h> using namespace std; int main() { int l, r; cin >> l >> r; int cnt = 0; long long sum = 0; for(int i = l; i <= r; ++i) { if((i & (i - 1)) != 0) { cnt += 1; sum += i; } } cout << cnt << " " << sum << endl; return 0; } 假设输入的 l r 均为不超过 106的正整数,且满足 l<=r,完成下面的判断题单选题。 ·判断题 16. 当输入为 2 5 时,程序的输出为 2 8。( ) 17. 程序的输出总是两个正整数。( ) 18. 将第 8 行的 long long 改为 int,程序行为不变。( ) ·单选题 19. 当输入为 1 100 时,程序的输出为( )。 A. 93 4923 B. 92 4823 C. 93 4823 D. 92 4923 20. 当输入为 10000 1000000 时,程序的第个输出为( )。 A. 989993 B. 989994 C. 989995 D. 989996 LUOGU SCP-J 2025 第C++语言试题 第 5 页,共 10 页 (2) 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std; int main() { int n, m; cin >> n >> m; vector<int> a(n); for(int i = 0; i < n; ++i) { cin >> a[i]; } vector<int> dp(m + 1); dp[0] = 0; for(int i = 1; i <= m; ++i) { int now = 0; for(int j = 0; j < n; ++j) { if(i >= a[j] && dp[i - a[j]] == 0) { now = a[j]; } } dp[i] = now; } cout << dp[m] << endl; return 0; } 假设输入的 n m 均为不超过 1000 的正整数,输入的 a[i]均为不超过 m 的正整数,完成下 面的判断题单选题。 判断题 21. 当输入为 3 5 1 3 4 时,程序的输出为 0。( ) 22. (2 分)当输入的数组 a 为{1}且 m 为偶数时,程序的输出为 0。( ) 23. 将第 16 行的条件 i >= a[j] && dp[i - a[j]] == 0 改为 dp[i - a[j]] == 0,程 序可能会产生编译错误。( ) LUOGU SCP-J 2025 第C++语言试题 第 6 页,共 10 页 ·单选题 24. 当输入为 4 13 1 2 3 4 时,程序的输出为( )。 A. 0 B. 1 C. 2 D. 3 25. 当输入为 7 1000 1 2 3 4 5 6 7 时,程序的输出为( )。 A. 0 B. 1 C. 2 D. 3 26. (4 分)当输入的数组 a 为{1,2,3,4,5}时,有( )个符合数据范围的整数 m 使得输 出为 3。 A. 165 B. 166 C. 167 D. 168 (3) 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include<bits/stdc++.h> using namespace std; vector <int> primes; int comp_by[2000005]; void sieve(int n) { for(int x = 2; x <= n; x++) { if(comp_by[x] == 0) primes.push_back(x); for(int i = 0; i < primes.size(); i++) { if(x * primes[i] > n) break; comp_by[x * primes[i]] = primes[i]; if(x % primes[i] == 0) break; } } } int main() { freopen("input.txt", "w", stdout); freopen("output.txt", "r", stdin); int n; cin >> n; sieve(n); for(int i = 1; i <= n; i++) cout << comp_by[i] << ' '; return 0; } LUOGU SCP-J 2025 第C++语言试题 第 7 页,共 10 页 假设输入的 n 是不超过 106的正整数,完成下面的判断题选择题。 提示:伯特兰-切比雪夫定理:对任意 n>1,存在质数 p 使得 n<p<2n。 ·判断题 27. 程序将从 input.txt 读入数据,输出到 output.txt。( ) 28. 交换程序的第 12 行第 13 行,不会导致数组越界。( ) 29. 对于所有正整数 i,满足 1<=i<=n,输出的第 i 个数是 0 当且仅当 i 是质数。( ) ·单选题 30. 该程序的的主要流程最接近( )。 A. 递归法 B. 动态规划 C. 埃拉托斯特尼筛 D. 欧拉筛 31. 将程序的第 14 行移动到第 11 行,当输入为 1000000 时,输出的第( )个数会发生 改变。 A. 75 B. 45 C. 97 D. 105 32. (4 分)当输入为 100 时,输出的所有数字之为( )。 A. 154 B. 194 C. 197 D. 214 三、完善程序(单选题,每小题 3 分,共计 30 分) (1)(全排列检查)给定长度为 n 的数组 a,判断其是否构成全排列。如果 1,2,...,n 都恰 好在数组 a 中出现且仅出现次,那么就称这个数组是个全排列。 试补全程序。 01 02 03 04 05 06 07 08 09 10 11 12 #include<bits/stdc++.h> using namespace std; bool is_permutation(vector<int> &a) { int n = ① ; vector<int> count(); for(int i = 0; i < n; i++) { if() count[a[i]]++; else ④ ; } LUOGU SCP-J 2025 第C++语言试题 第 8 页,共 10 页 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 for(int i = 1; i <= n; i++) if(count[ ⑤ ] > 1) return false; return true; } int main() { int n; cin >> n; vector<int> a(n); for(int i = 0; i < n; i++) cin >> a[i]; if(is_permutation(a)) cout << "The sequence is a permutation."; else cout << "The sequence is not a permutation."; return 0; } 33. ①处应填( )。 A. a.length() B. a.size() C. a.back() D. a.capacity() 34. ②处应填( )。 A. 0 B. n C. n + 1 D. 1000000000 35. ③处应填( )。 A. 1 <= a[i] && a[i] <= n B. 1 <= a[i] <= n C. 1 <= a[i] || a[i] <= n D. a[i] < 1 || a[i] > n 36. ④处应填( )。 A. break B. continue C. return true D. return false 37. ⑤处应填( )。 A. i B. a[i] C. i – 1 D. i / 2 (2)(跳跃)给定个数组 a[0],a[1],...,a[n-1],每次跳跃从从当前位置 x 跳至位置 a[x]。回答 q 次询问,每次给出(x,k),输出从 x 跳跃 k 次后的位置编号。 试补全程序。 LUOGU SCP-J 2025 第C++语言试题 第 9 页,共 1001 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> using namespace std; const int N = 100010, LOG = 20; int a[N], dp[N][LOG]; int main() { int n, q; cin >> n >> q; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n; i++) { dp[i][0] = ① ; } for (int k = 1; k < LOG; k++) { for (int i = 0; i < n; i++) { dp[i][k] = ② ; } } while (q--) { int x, k; cin >> x >> k; int u = x; for (int j = 0; j < LOG; j++) { if () { u = ④ ; } } cout << ⑤ << endl; } return 0; } 38. ①处应填( )。 A. i B. a[i] C. 0 D. dp[i][1] LUOGU SCP-J 2025 第C++语言试题 第 10 页,共 10 页 39. ②处应填( )。 A. dp[dp[i][k - 1]][k - 1] B. dp[i][k - 1] + dp[i][k - 1] C. dp[i - 1][k - 1] D. dp[k - 1][i] 40. ③处应填( )。 A. k & j B. k >> j C. (k >> j) & 1 D. (k >> j) ^ 1 41. ④处应填( )。 A. dp[j][u] B. dp[k][u] C. dp[u][j] D. a[u] 42. ⑤处应填( )。 A. u B. x C. k D. dp[u][0]
08-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值