[关闭]
@Dmaxiya 2020-08-25T00:41:14.000000Z 字数 3846 阅读 876

数论基础练习题解

Hello_World


exgcd

扩展欧几里得要解决的就是求解 整数解的问题。
首先证明:若方程有整数解,则 必然为 的整数倍。

,则 ,又因为 都是整数,所以 必然是 的整数倍。

进而求解:方程 的整数解。


比较系数可得:,当 时,,此时 即为方程 的解。

所以可以得出 代码如下:

  1. #define LL long long
  2. LL exgcd(LL a, LL b, LL &x, LL &y) {
  3. if(b == 0) {
  4. x = 1;
  5. y = 0;
  6. return a;
  7. }
  8. LL gcd = exgcd(a, b, x, y);
  9. LL tmp = x;
  10. x = y;
  11. y = tmp - a / b * y;
  12. return gcd;
  13. }

还可以通过判断 是否是返回值 的倍数,来计算 的解:

  1. LL cal(LL a, LL b, LL c) {
  2. LL x, y;
  3. LL gcd = exgcd(a, b, x, y);
  4. if(c % gcd != 0) {
  5. return -1;
  6. }
  7. LL MOD = abs(b / gcd);
  8. return (x % MOD + MOD) % MOD;
  9. }

该函数的功能是计算方程 的最小非负整数解,若无解,则返回 。注意这里 的下一个整数解为 ,而不是 ,读者请自行证明。
要得到 的解,且 为最小非负整数解,则 函数也可以写为:

  1. bool cal(LL a, LL b, LL c, LL &x, LL &y) {
  2. LL gcd = exgcd(a, b, x, y);
  3. if(c % gcd != 0) {
  4. return false;
  5. }
  6. LL MOD = abs(b / gcd);
  7. x = (x % MOD + MOD) % MOD;
  8. y = (c - a * x) / b;
  9. return true;
  10. }

2 月 26 日 数论基础练习

A. Sum of Consecutive Prime Numbers

题意

一个数字 可能可以由几个连续的素数相加得到,给定 ,求有几种连续的素数和为

数据范围

题解

素数打表,然后对素数做前缀和, 枚举起点,对于每个起点二分查找终点。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 10000 + 100;
  21. int n;
  22. bool vis[maxn];
  23. int prime[maxn];
  24. int sum[maxn];
  25. int *it;
  26. void Prime(int n) {
  27. for(LL i = 2; i < n; ++i) {
  28. if(!vis[i]) {
  29. prime[++prime[0]] = i;
  30. }
  31. for(int j = 1; j <= prime[0] && i * prime[j] < n; ++j) {
  32. int k = i * prime[j];
  33. vis[k] = true;
  34. if(i % prime[j] == 0) {
  35. break;
  36. }
  37. }
  38. }
  39. for(int i = 1; i <= prime[0]; ++i) {
  40. sum[i] = sum[i - 1] + prime[i];
  41. }
  42. }
  43. int main() {
  44. #ifdef LOCAL
  45. freopen("test.txt", "r", stdin);
  46. // freopen("out.txt", "w", stdout);
  47. #endif // LOCAL
  48. ios::sync_with_stdio(false);
  49. Prime(maxn);
  50. while(scanf("%d", &n), n != 0) {
  51. int ans = 0;
  52. for(int i = 0; i == 0 || prime[i] < n; ++i) {
  53. it = lower_bound(sum, sum + prime[0] + 1, sum[i] + n);
  54. if(*it == sum[i] + n) {
  55. ++ans;
  56. }
  57. }
  58. printf("%d\n", ans);
  59. }
  60. return 0;
  61. }

B. Romantic

题意

给定 ,计算 的最小非负整数解,若无解则输出“”。

数据范围

题解

裸题。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. LL a, b;
  21. LL exgcd(LL a, LL b, LL &x, LL &y) {
  22. if(b == 0) {
  23. x = 1;
  24. y = 0;
  25. return a;
  26. }
  27. LL d = exgcd(b, a % b, x, y);
  28. LL tmp = x;
  29. x = y;
  30. y = tmp - a / b * y;
  31. return d;
  32. }
  33. LL cal(LL a, LL b, LL c) {
  34. LL x, y;
  35. LL gcd = exgcd(a, b, x, y);
  36. if(gcd != 1) {
  37. return INT_MIN;
  38. }
  39. b = abs(b);
  40. return (x % b + b) % b;
  41. }
  42. int main() {
  43. #ifdef LOCAL
  44. freopen("test.txt", "r", stdin);
  45. // freopen("out.txt", "w", stdout);
  46. #endif // LOCAL
  47. ios::sync_with_stdio(false);
  48. while(scanf("%lld%lld", &a, &b) != EOF) {
  49. LL ans = cal(a, b, 1);
  50. if(ans == INT_MIN) {
  51. printf("sorry\n");
  52. } else {
  53. printf("%lld %lld\n", ans, (1 - a * ans) / b);
  54. }
  55. }
  56. return 0;
  57. }

C. Raising Modulo Numbers

题意

组数据,每组数据有 值,计算 的值。

数据范围

题解

快速幂裸题。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. int T, n;
  21. LL MOD, a, b, ans;
  22. LL fast_pow(LL res, LL n) {
  23. LL ans;
  24. for(ans = 1; n != 0; n >>= 1) {
  25. if((n & 1) == 1) {
  26. ans = (ans * res) % MOD;
  27. }
  28. res = (res * res) % MOD;
  29. }
  30. return ans;
  31. }
  32. int main() {
  33. #ifdef LOCAL
  34. freopen("test.txt", "r", stdin);
  35. // freopen("out.txt", "w", stdout);
  36. #endif // LOCAL
  37. ios::sync_with_stdio(false);
  38. scanf("%d", &T);
  39. while(T--) {
  40. ans = 0;
  41. scanf("%lld%d", &MOD, &n);
  42. for(int i = 0; i < n; ++i) {
  43. scanf("%lld%lld", &a, &b);
  44. ans += fast_pow(a, b);
  45. ans %= MOD;
  46. }
  47. printf("%lld\n", ans);
  48. }
  49. return 0;
  50. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注