指数循环节练习

1.HDU4335

我们先将n^{n!}\equiv b(mod\ p)转化为n^{n!%\varphi (p)+\varphi (p)}\equiv b(mod\ p).

然后分情况讨论:

1.n! <= phi(p)时,我们直接枚举有多少n满足条件即可

2.n! > phi(p)时,注意到,当出现一个 n 使得n! % phi(p) == 0,那么对于i > n,一定都有 i! % phi(p) == 0,因为 i! 包括 n!.所以,当n! % phi(p) != 0时,我们依旧枚举有多少个 n 满足条件.

3.当 n! % phi(p) == 0时,式子变成n^{phi(p)} \equiv b(mod\ p),这部分其实是存在循环节的,并且长度为p,具体证明可以查阅网上资料,这里不再赘述.我们求出每个循环节有多少个n是满足条件的即可.

最后补充一点,这道题的题给数据很大,尤其是对于ull_max 的情况,我们要进行特判,其他的数据也要开 ull 而不只是 ll

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <unordered_map>
#include <vector>
#include <stack>
#include <time.h>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define PII pair<int, int>
#define PDI pair<double, int>
#define int long long
#define ll long long
#define ull unsigned long long
#define eps 1e-6
#define MOD 1000000007
#define debug(a) cout << #a << "=" << a << endl;
#define all(x) (x).begin(), (x).end()
#define mem(x, y) memset((x), (y), sizeof(x))
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
ull b, p, m;
ull get_phi(int n) {
    ull ans = n;
    for (int i = 2; i <= n / i; ++i) {
        if (n % i == 0) {
            ans = ans / i * (i - 1);
            while (n % i == 0)
                n /= i;
        }
    }
    if (n > 1)
        ans = ans / n * (n - 1);
    return ans;
}
ull qpow(ull a, ull k, ull p) {
    ull res = 1;
    while (k) {
        if (k & 1)
            res = res * a % p;
        k >>= 1;
        a = a * a % p;
    }
    return res;
}
signed main() {
#ifdef LOCAL
    freopen("input.in", "r", stdin);
    freopen("output.out", "w", stdout);
#endif
    IOS;
    int T, Case = 0;
    cin >> T;
    while (T--) {
        cout << "Case #" << ++Case << ": ";
        cin >> b >> p >> m;
        if (p == 1) {
            if (m == 18446744073709551615ull)
                cout << "18446744073709551616\n";
            else
                cout << m + 1 << "\n";
            continue;
        }
        //1.i! <= phi(p)
        int i = 0, phi = get_phi(p);
        ull fac = 1, ans = 0;
        for (; i <= m && fac <= phi; ++i) {
            if (qpow(i, fac, p) == b)
                ++ans;
            fac *= i + 1;
        }
        //2.i! > phi(p) 且 i! % phi(p) != 0
        fac %= phi;
        for (; i <= m && fac; ++i) {
            if (qpow(i, fac + phi, p) == b)
                ++ans;
            fac = (fac * (i + 1)) % phi;
        }
        //3.i! % phi(p) = 0
        if (i <= m) {
            ull cnt = 0;//表示一个循环节中有多少个b
            vector<int> ring(p);
            for (int j = 0; j < p; ++j) {
                ring[j] = qpow(i + j, phi, p);
                if (ring[j] == b)
                    ++cnt;
            }
            ans += (ull)(m - i + 1) / p * cnt;
            ull remain = (m - i + 1) % p;
            for (int j = 0; j < remain; ++j)
                if (ring[j] == b)
                    ++ans;
        }
        cout << ans << "\n";
    }
    
}

2.hdu2837

 这道题我们直接使用递归并搭配欧拉降幂即可,比较奇怪的是这道题的边界判断(题主也不知道为什么会这样).

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <unordered_map>
#include <vector>
#include <stack>
#include <time.h>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define PII pair<int, int>
#define PDI pair<double, int>
#define int long long
#define ll long long
#define ull unsigned long long
#define eps 1e-6
#define MOD 1000000007
#define debug(a) cout << #a << "=" << a << endl;
#define all(x) (x).begin(), (x).end()
#define mem(x, y) memset((x), (y), sizeof(x))
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
int n, m;
int qpow(int a, int k, int p) {
    if (a == 0)
        return k == 0;
    int res = 1;
    while (k) {
        if (k & 1)
            res = res * a % p;
        k >>= 1;
        a = a * a % p;
    }
    return res == 0 ? p : res;
}
int phi(int x) {
    int ans = x;
    for (int i = 2; i <= x / i; ++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;
}
int dfs(int n, int m) {
    if (n == 0)
        return 1;
    if (n < 10)
        return n;
    return qpow(n % 10, dfs(n / 10, phi(m)), m);
}
signed main() {
#ifdef LOCAL
    freopen("input.in", "r", stdin);
    freopen("output.out", "w", stdout);
#endif
    IOS;
    int T;
    cin >> T;
    while (T--) {
        cin >> n >> m;
        cout << dfs(n, m) << "\n";
    }
}

3.Luogu P4139

 相比上面一题,这题可以直接套用欧拉降幂.

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <vector>
#include <unordered_map>
#include <stack>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define PII pair<int, int>
#define PDI pair<double, int>
#define int long long
#define ll long long
#define ull unsigned long long
#define debug(a) cout << #a << "=" << a << endl;
#define all(x) (x).begin(), (x).end()
#define sd(x) scanf("%d", &(x))
#define sddd(x, y, z) scanf("%lld%lld%lld", &(x), &(y), &(z))
using namespace std;
const int N = 1e7 + 10;
int phi[N], primes[N], tot;
bool vis[N];
int qmi(int a, int k, int p) {
    int res = 1;
    while (k) {
        if (k & 1)
            res = res * a % p;
        k >>= 1;
        a = a * a % p;
    }
    return res;
}
void euler() {
    phi[1] = 1;
    for (int i = 2; i <= 10000000; ++i) {
        if (vis[i] == 0) {
            primes[++tot] = i;
            phi[i] = i - 1;
        }
        for (int j = 1; j <= tot && i * primes[j] <= 10000000; ++j) {
            vis[i * primes[j]] = 1;
            if (i % primes[j] == 0) {
                phi[i * primes[j]] = phi[i] * primes[j];
                break;
            }else
                phi[i * primes[j]] = phi[i] * (primes[j] - 1);
        }
    }
}
int dfs(int u, int p) {
    if (p == 1)
        return 0;
    return qmi(u, dfs(u, phi[p]) + phi[p], p);
}
void solve() {
    int p;
    cin >> p;
    cout << dfs(2, p) << "\n";
}
signed main() {
#ifdef LOCAL
    freopen("input.in", "r", stdin);
    freopen("output.out", "w", stdout);
#endif
    IOS;
    euler();
    int T;
    cin >> T;
    while (T--)
        solve();
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值