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

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

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

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

思路

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

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

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

$$

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

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

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 的情况

代码

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

#include <bits/stdc++.h>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
const double pi = 3.14159265358979;
const int maxn = 1e3 + 5;
const int maxm = 1e3 + 5;
const int mod = 1e9 + 7;

ll f(ll x, ll a)
{
    if(x < 1)return -1;
    return 1 + f((ll)(log(x) / log(a)), a);
}

inline ll modulo(ll x, ll mod){return x < mod ? x : x % mod + mod;}
inline ll pow_(ll a, ll b, ll p)
{
    ll ret = 1;
    while(b)
    {
        if(b & 1)ret = modulo(ret * a, p);
        a = modulo(a * a, p);
        b >>= 1;
    }
    return ret;
}
inline ll phi(ll x)
{
    ll ans = x;
    for(ll i = 2; i * i <= x; ++i)
    {
        if(x % i == 0)
        {
            ans = ans / i * (i - 1);
            while(x % i == 0)x /= i;
        }
    }
    if(x > 1)ans = ans / x * (x - 1);
    return ans;
}
ll gcd(ll a, ll b)
{
    if(b == 0)return a;
    return gcd(b, a % b);
}
ll f(ll a, ll b, ll k, ll p)
{
    if(p == 1)return 1;
    if(k == 0)return 1;
    return pow_(a, f(a, a, k - 1, phi(p)), p);
}

int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    // ios_base::sync_with_stdio(0);
    // cin.tie(0);cout.tie(0);

    int t; cin >> t;
    while(t--)
    {
        ll a, b, m;
        cin >> a >> b >> m;
        // cout << a << b << m << endl;
        if(b == 0)
        {
            cout << 1 % m << endl;
            continue;
        }
        ll ans = f(a, a, b, m) % m;
        // if(a == 1)ans = 1 % m;
        // cout << ans << " " << ans % m << endl;
        cout << ans << endl;
    }

    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

pair记录上一层

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

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1000010;
int prime[N + 1], isprime[N + 1];
int tot, phi[N + 1];
struct P
{
    ll ans;
    bool v;
    P(ll _ans, bool _v)
    {
        ans = _ans;
        v = _v;
    }
};
ll gcd(ll a, ll b)
{
    return b ? gcd(b, a % b) : a;
}
P qpow(ll A, ll B, ll C)
{
    ll re = 1;
    bool flag = 1;
    while (B)
    {
        if (B & 1)
        {
            if ((re *= A) >= C)
                flag = 0;
            re = re % C;
        }
        B = B >> 1;
        if (B)
        {
            if (A >= C)
                flag = 0;
            A %= C;
            if ((A *= A) >= C)
                flag = 0;
            A %= C;
        }
    }
    return P(re, flag);
}
void getphi()
{
    phi[1] = 1;
    isprime[1] = 1;
    for (int i = 2; i <= N; i++)
    {
        if (!isprime[i])
        {
            prime[++tot] = i;
            phi[i] = i - 1;
        }
        for (int j = 1; j <= tot && i * prime[j] <= N; j++)
        {
            isprime[i * prime[j]] = 1;
            if (i % prime[j] == 0)
            {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            else
                phi[i * prime[j]] = phi[i] * phi[prime[j]];
        }
    }
}
inline ll Euler(ll x)
{
    return phi[x];
    //题目可以再复杂一点模数可以到longlong
    // ll ans = x;
    // for (int i = 1; i <= tot && prime[i] * prime[i] <= x; i++)
    // {
    //     if (x % prime[i] == 0)
    //     {
    //         ans = ans / prime[i] * (prime[i] - 1);
    //         while (x % prime[i] == 0)
    //             x /= prime[i];
    //     }
    // }
    // if (x > 1)
    //     ans = ans / x * (x - 1);
    // return ans;
}
P f(ll a, ll b, ll k, ll p)
{
    if (p == 1)
        return P(0, 0);
    if (k == 0)
        return P(a % p, a < p);
    ll ep = Euler(p);
    P tmp = f(b, b, k - 1, ep);
    if (gcd(a, p) == 1)
        return qpow(a, tmp.ans, p);
    if (tmp.v == false)
    {
        tmp.ans += ep;
    }
    return qpow(a, tmp.ans, p);
}
int main()
{
    //double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ll a, b, k, p;
    getphi();
    int t;
    while (~scanf("%d", &t))
    {
        while (t--)
        {
            scanf("%lld %lld %lld", &a, &k, &p);
            b = a;
            if(k == 0)
            {
                printf("%lld\n", 1 % p);
                continue;
            }
            printf("%lld\n", f(a, b, k - 1, p).ans);
        }
    }
    //cout<<(clock()-pp)/CLOCKS_PER_SEC;
    return 0;
}

cf-906 D. Power Tower

cf-906 D. Power Tower

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

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

#include <bits/stdc++.h>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
const double pi = 3.14159265358979;
const int maxn = 1e5 + 5;
const int maxm = 1e3 + 5;
const int mod = 1e9 + 7;

ll a[maxn];

inline ll modulo(ll x, ll mod){return x < mod ? x : x % mod + mod;}
inline ll pow_(ll a, ll b, ll p)
{
    ll ret = 1;
    while(b)
    {
        if(b & 1)ret = modulo(ret * a, p);
        a = modulo(a * a, p);
        b >>= 1;
    }
    return ret;
}
unordered_map<ll, ll> phi_;
inline ll phi(ll x)
{
    if(phi_[x])return phi_[x];
    ll ans = x;
    ll t = x;
    for(ll i = 2; i * i <= x; ++i)
    {
        if(x % i == 0)
        {
            ans = ans / i * (i - 1);
            while(x % i == 0)x /= i;
        }
    }
    if(x > 1)ans = ans / x * (x - 1);
    phi_[t] = ans;
    return ans;
}
//这里根据题意来更改,k表示共有k个指数
ll f(ll a, ll b, ll k, ll p)
{
    if(p == 1)return 1;
    if(k == 0)return 1;
    return pow_(a, f(a, a, k - 1, phi(p)), p);
}
ll f(ll l, ll r, ll p)
{
    if(p == 1)return 1;
    if(l == r + 1)return 1;
    return pow_(a[l], f(l + 1, r, phi(p)), p);
}

int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    ll n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; ++i)cin >> a[i];
    int q; cin >> q;
    while(q--)
    {
        ll l, r; cin >> l >> r;
        cout << f(l, r, m) % m << endl;
    }

    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

cf-gym-101550 E Exponial

cf-gym-101550 E Exponial

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

#include <bits/stdc++.h>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;
const double pi = 3.14159265358979;
const int maxn = 1e5 + 5;
const int maxm = 1e3 + 5;
const int mod = 1e9 + 7;

inline ll modulo(ll x, ll mod){return x < mod ? x : x % mod + mod;}
inline ll pow_(ll a, ll b, ll p)
{
    ll ret = 1;
    while(b)
    {
        if(b & 1)ret = modulo(ret * a, p);
        a = modulo(a * a, p);
        b >>= 1;
    }
    return ret;
}
unordered_map<ll, ll> phi_;
inline ll phi(ll x)
{
    if(phi_[x])return phi_[x];
    ll ans = x;
    ll t = x;
    for(ll i = 2; i * i <= x; ++i)
    {
        if(x % i == 0)
        {
            ans = ans / i * (i - 1);
            while(x % i == 0)x /= i;
        }
    }
    if(x > 1)ans = ans / x * (x - 1);
    phi_[t] = ans;
    return ans;
}

// ll f(ll l, ll r, ll p)
// {
//     if(p == 1)return 1;
//     if(l == r + 1)return 1;
//     return pow_(a[l], f(l + 1, r, phi(p)), p);
// }

ll f(ll a, ll p)
{
    if(p == 1)return 1;
    if(a == 1)return 1;
    return pow_(a, f(a - 1, phi(p)), p);
}

int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    ll n, m;
    while(cin >> n >> m)cout << f(n, m) % m << endl;

    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

貌似够了,,,数论是最不想碰的东西,,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. 分布式任务调度平台XXL-JOB学习笔记一

    分布式任务调度平台XXL-JOB学习笔记一 XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码并接入多家公司线上产品线,开箱即用.码云地址 ...

  2. mysql 不同版本下 group by 组内排序的差异

    最近发现网上找的 group by 组内排序语句在不同的mysql版本中结果不一样.   建表语句:   SET FOREIGN_KEY_CHECKS=0;   -- ---------------- ...

  3. (11)ASP.NET Core 中的配置一(Configuration)

    1.前言 ASP.NET Core在应用程序上引入Microsoft.Extensions.Configuration配置,可以支持多种方式配置,包括命令行配置.环境变量配置.文件配置.内存配置,自定 ...

  4. 细说RESTFul API之版本管理

    目录 接口实现版本管理的意义 如何实现接口的版本管理 项目实战 接口实现版本管理的意义 API版本管理的重要性不言而喻,对于API的设计者和使用者而言,版本管理都有着非常重要的意义. 首先,对于API ...

  5. .net持续集成sonarqube篇之 sonarqube与jenkins集成(命令模式)

    系列目录 Sonarqube结合Jenkins与常见问题 我们引入sonarqube组件的最终目的是要为整个Ci环境服务的,如果不能集成于当前的Jenkins CI,那么我们做的很多关于sonarqu ...

  6. 关于JS、JQ首行首列固定展示

    当时遇见这个问题 是医院手麻系统大批量数据展示,由于是旧项目系统没有使用到前端的架构 只能使用JQ,JS, css完成 也谢谢给予我支持的同行们 固定首行数据: 采用函数的方式进行  JQ /** * ...

  7. c#将字符串转化为合理的文件名

    string name = System.Text.RegularExpressions.Regex.Replace(url, "[<>/\\|:\"?*]" ...

  8. 【POJ - 2236】Wireless Network (并查集)

    Wireless Network 这接翻译了 Descriptions 地震发生在东南亚.ACM(亚洲合作医疗团队)已经与膝上电脑建立了无线网络,但是一次意外的余震袭击,网络中的所有计算机都被打破了. ...

  9. 一文了解:Redis的AOF持久化

    Redis的AOF持久化 每当Redis-Server接收到写数据时,就把命令以文本形式追加到AOF文件里,当重启Redis服务时,AOF文件里的命令会被重新执行一次,重新恢复数据.当AOF过大时将重 ...

  10. Java虚拟机(二)-对象创建

    这一篇大致说明一下,对象在Java堆中对象分配.内存布局以及访问定位 1.对象的创建 虚拟机在遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引 ...