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. 织梦(dede)底层模板概念、常用底层模板字段

    织梦(dede)底层模板概念.常用底层模板字段 一.底层模板的概念以及调用方式: 1. 什么是底层模板? 底层模板不是一个模板! 他就是在实际页面当中所要显示的具体内容: 2. 底层模板的应用: 调用 ...

  2. HTTP 400 Bad request 原因

    我在使用httpclient 发送http请求时遇到问题,请求报 400 Bad request.网上都在说下面这两个原因 400 是 HTTP 的状态码,主要有两种形式: 1.bad request ...

  3. vue使用video.js解决m3u8视频播放格式

    今天被这个关于m3u8视频播放不了搞了一下午,这个项目所有的视频流都是m3u8格式的,后台给我们返回的都是m3u8格式的视频流,解决了好长时间,看了好多博客,只有这个博客给我点启发,去解决这个问题,请 ...

  4. Angular JS 中的内置方法之表单验证

    angular js 结合html5 可以实现强大的表单验证功能 关闭html5自带的表单验证功能可以用

  5. DesignPattern系列__01SingletonResponsibility

    单一职责原则 单一职责原则:一个类应该只有一个原因引起改变,即一个类应该只负责一个业务逻辑. 问题由来:类T负责t1, t2两个职责,当因为t1j对类T修改的时候,可能导致类T出现问题而影响职责t2. ...

  6. Go slice:切片的“陷阱”和本质

    文章说明 总结了go语言中切片slice的特殊性和使用时的注意事项. 个人理解,不足之处欢迎指出. slice:切片,是go语言中一种常用的数据结构,基于数组构建,表示相同数据类型的集合. 数组 Go ...

  7. js中数组和对象的合并

    1 数组合并 1.1 concat 方法 1 2 3 4 var a=[1,2,3],b=[4,5,6]; var c=a.concat(b); console.log(c);// 1,2,3,4,5 ...

  8. kubernetes API服务器的安全防护

    12.1.了解认证机制 启动API服务器时,通过命令行选项可以开启认证插件. 12.1.1.用户和组 了解用户: 分为两种连接到api服务器的客户端: 1.真实的人 2.pod,使用一种称为Servi ...

  9. 使用python画2D线条

    """用于验证整体趋势正确性,不做关闭操作时保持显示""" #!python3 #-*- coding:utf-8 -*- import m ...

  10. 学习spark 技术

    spark sql 可以说是 spark 中的精华部分了,我感觉整体复杂度是 spark streaming 的 5 倍以上,现在 spark 官方主推 structed streaming, spa ...