https://www.cnblogs.com/31415926535x/p/11447033.html

曾今一时的懒,造就今日的泪

记得半年前去武大参加的省赛,当时的A题就是一个广义欧拉降幂的板子题,后来回来补了一下,因为没有交的地方,于是就测了数据就把代码扔了,,,然后,,昨天的南京网络赛就炸了,,,一样的广义欧拉降幂的板子题,,然后因为忘记了当初自己想出来的那中写法,,一直想着回想起之前的写法,,然后到结束都没弄出来,,,emmmm,,

赛后看了一下别人的解法,,别人的处理方法很巧妙,,当然另一个种返回两个值的(pair)的解法就是武大的标程,,,,(到最后之前想出的写法还是每能推出来,,都开始怀疑自己当时有没有真的推出来,,,,,

思路

广义欧拉降幂没啥好说的,,就是那个公式:

$$
对于求 a^b(mod  p)可以转换为:

  1. a^b = \begin{cases}
  2. a^{b \% \phi (p)} &gcd(a, p)=1 \\
  3. a^b &gcd(a, p) \neq 1, b < \phi (p) \\
  4. a^{b \% \phi (p) + \phi (p)} &gcd(a, p) \neq 1, b \ge \phi (p)
  5. \end{cases}

$$

公式很简单,,但是如果是求 \(a_1^{a_2^{a_3^{...}}} (mod \ p)\) 类似这样的值的话,显然要递归从上往下求(刚开始弄成了从下往上求,,口胡了一段时间,,,,),,但是再递归求的时候要考虑每一次 \(b\) 和 \(\phi (p)\) 的关系,,然后选择哪一个等式,,,这样就麻烦了,,可以用一个 pair 什么的来保存一个标志变量来决定递归的上一层要不要 \(+ \phi (p)\) ,,另一种巧妙地方式是修改一下 取模 的过程,,这样就不用考虑了,,,具体的推导过程在这里

所有的取模的步骤改成这样:

  1. inline ll modulo(ll x, ll mod){return x < mod ? x : x % mod + mod;}

这样保证 \(b \ge \phi (p)\),,然后就少了判断的情况

题目

南京网络赛B supper_log

南京网络赛B supper_log

这道题按题目的意思推几项样例就能看出是要求一个 \(a^{a^{a^{a^{...}}}} mod \ m (一共有b个a)\) 的值,,直接降幂求就可以了,, 记得特判 b=0 的情况

代码

群里很多大佬用的方法,重置取模的流程

  1. #include <bits/stdc++.h>
  2. #define aaa cout<<233<<endl;
  3. #define endl '\n'
  4. #define pb push_back
  5. using namespace std;
  6. typedef long long ll;
  7. typedef unsigned long long ull;
  8. typedef long double ld;
  9. // mt19937 rnd(time(0));
  10. const int inf = 0x3f3f3f3f;//1061109567 > 1e9
  11. const ll linf = 0x3f3f3f3f3f3f3f3f;
  12. const double eps = 1e-7;
  13. const double pi = 3.14159265358979;
  14. const int maxn = 1e3 + 5;
  15. const int maxm = 1e3 + 5;
  16. const int mod = 1e9 + 7;
  17. ll f(ll x, ll a)
  18. {
  19. if(x < 1)return -1;
  20. return 1 + f((ll)(log(x) / log(a)), a);
  21. }
  22. inline ll modulo(ll x, ll mod){return x < mod ? x : x % mod + mod;}
  23. inline ll pow_(ll a, ll b, ll p)
  24. {
  25. ll ret = 1;
  26. while(b)
  27. {
  28. if(b & 1)ret = modulo(ret * a, p);
  29. a = modulo(a * a, p);
  30. b >>= 1;
  31. }
  32. return ret;
  33. }
  34. inline ll phi(ll x)
  35. {
  36. ll ans = x;
  37. for(ll i = 2; i * i <= x; ++i)
  38. {
  39. if(x % i == 0)
  40. {
  41. ans = ans / i * (i - 1);
  42. while(x % i == 0)x /= i;
  43. }
  44. }
  45. if(x > 1)ans = ans / x * (x - 1);
  46. return ans;
  47. }
  48. ll gcd(ll a, ll b)
  49. {
  50. if(b == 0)return a;
  51. return gcd(b, a % b);
  52. }
  53. ll f(ll a, ll b, ll k, ll p)
  54. {
  55. if(p == 1)return 1;
  56. if(k == 0)return 1;
  57. return pow_(a, f(a, a, k - 1, phi(p)), p);
  58. }
  59. int main()
  60. {
  61. // double pp = clock();
  62. // freopen("233.in", "r", stdin);
  63. // freopen("233.out", "w", stdout);
  64. // ios_base::sync_with_stdio(0);
  65. // cin.tie(0);cout.tie(0);
  66. int t; cin >> t;
  67. while(t--)
  68. {
  69. ll a, b, m;
  70. cin >> a >> b >> m;
  71. // cout << a << b << m << endl;
  72. if(b == 0)
  73. {
  74. cout << 1 % m << endl;
  75. continue;
  76. }
  77. ll ans = f(a, a, b, m) % m;
  78. // if(a == 1)ans = 1 % m;
  79. // cout << ans << " " << ans % m << endl;
  80. cout << ans << endl;
  81. }
  82. // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
  83. return 0;
  84. }

pair记录上一层

武大那场的标程,,直接改了下输入,,

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. const int N = 1000010;
  5. int prime[N + 1], isprime[N + 1];
  6. int tot, phi[N + 1];
  7. struct P
  8. {
  9. ll ans;
  10. bool v;
  11. P(ll _ans, bool _v)
  12. {
  13. ans = _ans;
  14. v = _v;
  15. }
  16. };
  17. ll gcd(ll a, ll b)
  18. {
  19. return b ? gcd(b, a % b) : a;
  20. }
  21. P qpow(ll A, ll B, ll C)
  22. {
  23. ll re = 1;
  24. bool flag = 1;
  25. while (B)
  26. {
  27. if (B & 1)
  28. {
  29. if ((re *= A) >= C)
  30. flag = 0;
  31. re = re % C;
  32. }
  33. B = B >> 1;
  34. if (B)
  35. {
  36. if (A >= C)
  37. flag = 0;
  38. A %= C;
  39. if ((A *= A) >= C)
  40. flag = 0;
  41. A %= C;
  42. }
  43. }
  44. return P(re, flag);
  45. }
  46. void getphi()
  47. {
  48. phi[1] = 1;
  49. isprime[1] = 1;
  50. for (int i = 2; i <= N; i++)
  51. {
  52. if (!isprime[i])
  53. {
  54. prime[++tot] = i;
  55. phi[i] = i - 1;
  56. }
  57. for (int j = 1; j <= tot && i * prime[j] <= N; j++)
  58. {
  59. isprime[i * prime[j]] = 1;
  60. if (i % prime[j] == 0)
  61. {
  62. phi[i * prime[j]] = phi[i] * prime[j];
  63. break;
  64. }
  65. else
  66. phi[i * prime[j]] = phi[i] * phi[prime[j]];
  67. }
  68. }
  69. }
  70. inline ll Euler(ll x)
  71. {
  72. return phi[x];
  73. //题目可以再复杂一点模数可以到longlong
  74. // ll ans = x;
  75. // for (int i = 1; i <= tot && prime[i] * prime[i] <= x; i++)
  76. // {
  77. // if (x % prime[i] == 0)
  78. // {
  79. // ans = ans / prime[i] * (prime[i] - 1);
  80. // while (x % prime[i] == 0)
  81. // x /= prime[i];
  82. // }
  83. // }
  84. // if (x > 1)
  85. // ans = ans / x * (x - 1);
  86. // return ans;
  87. }
  88. P f(ll a, ll b, ll k, ll p)
  89. {
  90. if (p == 1)
  91. return P(0, 0);
  92. if (k == 0)
  93. return P(a % p, a < p);
  94. ll ep = Euler(p);
  95. P tmp = f(b, b, k - 1, ep);
  96. if (gcd(a, p) == 1)
  97. return qpow(a, tmp.ans, p);
  98. if (tmp.v == false)
  99. {
  100. tmp.ans += ep;
  101. }
  102. return qpow(a, tmp.ans, p);
  103. }
  104. int main()
  105. {
  106. //double pp = clock();
  107. // freopen("233.in", "r", stdin);
  108. // freopen("233.out", "w", stdout);
  109. ll a, b, k, p;
  110. getphi();
  111. int t;
  112. while (~scanf("%d", &t))
  113. {
  114. while (t--)
  115. {
  116. scanf("%lld %lld %lld", &a, &k, &p);
  117. b = a;
  118. if(k == 0)
  119. {
  120. printf("%lld\n", 1 % p);
  121. continue;
  122. }
  123. printf("%lld\n", f(a, b, k - 1, p).ans);
  124. }
  125. }
  126. //cout<<(clock()-pp)/CLOCKS_PER_SEC;
  127. return 0;
  128. }

cf-906 D. Power Tower

cf-906 D. Power Tower

突然很多人交这道两年前的题啊,,hhhhh

这题也是降幂,他是求的一个指数序列的一个区间的幂的值,,,套路一样,,就是这个模数很大,,不能每次都算他的 phi ,,不然会超时,,所以要记忆化一下 unordered_map 一下,,或者 预处理一下模数的所有phi 因为对一个数一直求 phi 下去,,其实个数不多,,,

  1. #include <bits/stdc++.h>
  2. #define aaa cout<<233<<endl;
  3. #define endl '\n'
  4. #define pb push_back
  5. using namespace std;
  6. typedef long long ll;
  7. typedef unsigned long long ull;
  8. typedef long double ld;
  9. // mt19937 rnd(time(0));
  10. const int inf = 0x3f3f3f3f;//1061109567 > 1e9
  11. const ll linf = 0x3f3f3f3f3f3f3f3f;
  12. const double eps = 1e-7;
  13. const double pi = 3.14159265358979;
  14. const int maxn = 1e5 + 5;
  15. const int maxm = 1e3 + 5;
  16. const int mod = 1e9 + 7;
  17. ll a[maxn];
  18. inline ll modulo(ll x, ll mod){return x < mod ? x : x % mod + mod;}
  19. inline ll pow_(ll a, ll b, ll p)
  20. {
  21. ll ret = 1;
  22. while(b)
  23. {
  24. if(b & 1)ret = modulo(ret * a, p);
  25. a = modulo(a * a, p);
  26. b >>= 1;
  27. }
  28. return ret;
  29. }
  30. unordered_map<ll, ll> phi_;
  31. inline ll phi(ll x)
  32. {
  33. if(phi_[x])return phi_[x];
  34. ll ans = x;
  35. ll t = x;
  36. for(ll i = 2; i * i <= x; ++i)
  37. {
  38. if(x % i == 0)
  39. {
  40. ans = ans / i * (i - 1);
  41. while(x % i == 0)x /= i;
  42. }
  43. }
  44. if(x > 1)ans = ans / x * (x - 1);
  45. phi_[t] = ans;
  46. return ans;
  47. }
  48. //这里根据题意来更改,k表示共有k个指数
  49. ll f(ll a, ll b, ll k, ll p)
  50. {
  51. if(p == 1)return 1;
  52. if(k == 0)return 1;
  53. return pow_(a, f(a, a, k - 1, phi(p)), p);
  54. }
  55. ll f(ll l, ll r, ll p)
  56. {
  57. if(p == 1)return 1;
  58. if(l == r + 1)return 1;
  59. return pow_(a[l], f(l + 1, r, phi(p)), p);
  60. }
  61. int main()
  62. {
  63. // double pp = clock();
  64. // freopen("233.in", "r", stdin);
  65. // freopen("233.out", "w", stdout);
  66. ios_base::sync_with_stdio(0);
  67. cin.tie(0);cout.tie(0);
  68. ll n, m;
  69. cin >> n >> m;
  70. for(int i = 1; i <= n; ++i)cin >> a[i];
  71. int q; cin >> q;
  72. while(q--)
  73. {
  74. ll l, r; cin >> l >> r;
  75. cout << f(l, r, m) % m << endl;
  76. }
  77. // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
  78. return 0;
  79. }

cf-gym-101550 E Exponial

cf-gym-101550 E Exponial

这题是求一个 \(n^{{n-1}^{{n-2}^{{n-3}^{{...}^{1}}}}} mod \ p\) ,,,用上面的板子改一改就可以了,,,

  1. #include <bits/stdc++.h>
  2. #define aaa cout<<233<<endl;
  3. #define endl '\n'
  4. #define pb push_back
  5. using namespace std;
  6. typedef long long ll;
  7. typedef unsigned long long ull;
  8. typedef long double ld;
  9. // mt19937 rnd(time(0));
  10. const int inf = 0x3f3f3f3f;//1061109567 > 1e9
  11. const ll linf = 0x3f3f3f3f3f3f3f3f;
  12. const double eps = 1e-7;
  13. const double pi = 3.14159265358979;
  14. const int maxn = 1e5 + 5;
  15. const int maxm = 1e3 + 5;
  16. const int mod = 1e9 + 7;
  17. inline ll modulo(ll x, ll mod){return x < mod ? x : x % mod + mod;}
  18. inline ll pow_(ll a, ll b, ll p)
  19. {
  20. ll ret = 1;
  21. while(b)
  22. {
  23. if(b & 1)ret = modulo(ret * a, p);
  24. a = modulo(a * a, p);
  25. b >>= 1;
  26. }
  27. return ret;
  28. }
  29. unordered_map<ll, ll> phi_;
  30. inline ll phi(ll x)
  31. {
  32. if(phi_[x])return phi_[x];
  33. ll ans = x;
  34. ll t = x;
  35. for(ll i = 2; i * i <= x; ++i)
  36. {
  37. if(x % i == 0)
  38. {
  39. ans = ans / i * (i - 1);
  40. while(x % i == 0)x /= i;
  41. }
  42. }
  43. if(x > 1)ans = ans / x * (x - 1);
  44. phi_[t] = ans;
  45. return ans;
  46. }
  47. // ll f(ll l, ll r, ll p)
  48. // {
  49. // if(p == 1)return 1;
  50. // if(l == r + 1)return 1;
  51. // return pow_(a[l], f(l + 1, r, phi(p)), p);
  52. // }
  53. ll f(ll a, ll p)
  54. {
  55. if(p == 1)return 1;
  56. if(a == 1)return 1;
  57. return pow_(a, f(a - 1, phi(p)), p);
  58. }
  59. int main()
  60. {
  61. // double pp = clock();
  62. // freopen("233.in", "r", stdin);
  63. // freopen("233.out", "w", stdout);
  64. ios_base::sync_with_stdio(0);
  65. cin.tie(0);cout.tie(0);
  66. ll n, m;
  67. while(cin >> n >> m)cout << f(n, m) % m << endl;
  68. // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
  69. return 0;
  70. }

貌似够了,,,数论是最不想碰的东西,,emmmm,,,但又时不得不稍稍掌握的东西,,,,

(end....)

ACM-数论-广义欧拉降幂的更多相关文章

  1. Power Tower(广义欧拉降幂)

    题意:https://codeforc.es/contest/906/problem/D 计算区间的: ai ^ ai+1 ^ ai+2.......ar . 思路: 广义欧拉降幂: 注意是自下而上递 ...

  2. 广义欧拉降幂(欧拉定理)——bzoj3884,fzu1759

    广义欧拉降幂对于狭义欧拉降幂任然适用 https://blog.csdn.net/qq_37632935/article/details/81264965?tdsourcetag=s_pctim_ai ...

  3. Codeforces Round #454 D. Power Tower (广义欧拉降幂)

    D. Power Tower time limit per test 4.5 seconds memory limit per test 256 megabytes input standard in ...

  4. The Preliminary Contest for ICPC Asia Nanjing 2019 B. super_log (广义欧拉降幂)

    In Complexity theory, some functions are nearly O(1)O(1), but it is greater then O(1)O(1). For examp ...

  5. BZOJ 3884——欧拉降幂和广义欧拉降幂

    理论部分 欧拉定理:若 $a,n$ 为正整数,且 $a,n$ 互质,则 $a^{\varphi (n)} \equiv 1(mod \ n)$. 降幂公式: $$a^b=\begin{cases}a^ ...

  6. Codeforces Round #454 (Div. 1) CodeForces 906D Power Tower (欧拉降幂)

    题目链接:http://codeforces.com/contest/906/problem/D 题目大意:给定n个整数w[1],w[2],……,w[n],和一个数m,然后有q个询问,每个询问给出一个 ...

  7. 2018牛客网暑期ACM多校训练营(第四场) A - Ternary String - [欧拉降幂公式][扩展欧拉定理]

    题目链接:https://www.nowcoder.com/acm/contest/142/A 题目描述 A ternary string is a sequence of digits, where ...

  8. 数学--数论--欧拉降幂--P5091 欧拉定理

    题目背景 出题人也想写有趣的题面,可惜并没有能力. 题目描述 给你三个正整数,a,m,ba,m,ba,m,b,你需要求:ab mod ma^b \bmod mabmodm 输入格式 一行三个整数,a, ...

  9. hdu 1286:找新朋友(数论,欧拉函数)

    找新朋友 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

随机推荐

  1. IIS短文件名漏洞复现

    IIS短文件名漏洞复现 一.漏洞描述 此漏洞实际是由HTTP请求中旧DOS 8.3名称约定(SFN)的代字符(~)波浪号引起的.它允许远程攻击者在Web根目录下公开文件和文件夹名称(不应该可被访问). ...

  2. 简单的JSP分页显示

    1.mysql的limit关键字 (DAO) select * from tablename limit startPoint, numberPerPage; tablename 就是要分页显示的那张 ...

  3. 【iOS】使用 CocoaPods 导入文件没有提示

    解决方法: 选择工程的 TAEGETS -> Build Settings, 找到 Search Paths 下的 User Header Search Paths选项,如图所示: 点击 “+” ...

  4. Spark Streaming消费Kafka Direct保存offset到Redis,实现数据零丢失和exactly once

    一.概述 上次写这篇文章文章的时候,Spark还是1.x,kafka还是0.8x版本,转眼间spark到了2.x,kafka也到了2.x,存储offset的方式也发生了改变,笔者根据上篇文章和网上文章 ...

  5. Asp.Net MVC HttpPost用法

    一个Action只能用一个http 特性,例如:HttpPost 不能与HttpGet 或者多个HttpPost重复使用,否则会出错 也可以用 [AcceptVerbs("put" ...

  6. Jenkins Java 反序列化远程执行代码漏洞(CVE-2017-1000353)

    Jenkins Java 反序列化远程执行代码漏洞(CVE-2017-1000353) 一.漏洞描述 该漏洞存在于使用HTTP协议的双向通信通道的具体实现代码中,jenkins利用此通道来接收命令,恶 ...

  7. Wpf窗口设置屏幕居中最前显示

    public Window()         {             InitializeComponent();             WindowStartupLocation = Win ...

  8. hadoop学习(二)----HDFS简介及原理

    前面简单介绍了hadoop生态圈,大致了解hadoop是什么.能做什么.带着这些目的我们深入的去学习他.今天一起看一下hadoop的基石--文件存储.因为hadoop是运行与集群之上,处于分布式环境之 ...

  9. docker-compose 综合训练

    Docker-compose综合训练 一. 实验目的: 熟悉Docker-compose的基本工作原理: 熟悉Docker-compose安装 熟悉Docker compose命令基础 熟悉Docke ...

  10. .NETCore C# 中级篇2-4 一文带你完全弄懂正则表达式

    .NETCoreCSharp 中级篇2-4 本节内容为正则表达式的使用 简介 有的时候,你是否有过这种需求:判断一个Ip地址.邮箱.密码规则是否合法.如果让你使用if一类的传统方法进行处理,你肯定会被 ...