数论(欧拉降幂和质数分解数) ——杭电多校赛第九场E

数论(欧拉降幂)

——杭电多校赛第九场E

给定 a ,b ,c , d , x, y 求
在这里插入图片描述

0⩽a,b,c,d⩽3×106,0 首先对问题转化为枚举质因子,计算为每个公共质因子贡献的问题。规模为O(log x + log y)乘积就转化成了和的形式只需求出此式(指数)然后快速幂即可。
这里还要用到一个原理就是指数可能会爆long long 所以就是用到一个欧拉降幂,原理我也是看不懂,但是公式记住先。在快速幂取模时指数对mod-1取余,其他还是不变对mod取余。或者这里就是可以用_int128来做哦。

#include
using namespace std;

typedef long long ll;
const ll mod = 998244353;
const ll md = 998244352;
vector<pair<ll,ll> > v;

void div(ll n)
{
    v.clear();
    ll k = sqrt(n);
    for (ll i = 2; i <= k; ++ i) {
        ll cnt = 0;
        while (n % i == 0) {
            n /= i;
            cnt ++;
        }
        v.push_back({i, cnt});
    }
    if (n != 1) {
        v.push_back({n, 1});
    }
}

ll phi(ll n)
{
    ll ans = n;
    ll k = sqrt(n);
    for (int i = 2; i <= k; ++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;
}

ll pow(ll a, ll b, ll p) {
    ll res = 1;
    while (b) {
        if (b & 1) res = (res * a) % p;
        a = a * a % p;
        b >>= 1;
    }
    return res%p;
}

int main()
{
    ll a, b, c, d, x, y;
    scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &x, &y);
    a = max(1LL, a);
    c = max(1LL, c);
    --c;
    div(x);
    ll ans = 1;
    for (int i = 0; i < (int)v.size(); ++ i) {
        ll cnt = 0;
        while (y % v[i].first == 0) {
            y /= v[i].first;
            ++ cnt;
        }
        ll sum = 0;
        if (cnt == 0) continue;
        for (ll j = a; j <= b; ++ j) {
            ll e = v[i].second * (ll)j;
            ll f = e/cnt;
            while (cnt * f < e) {
                ++ f;
            }
            if (c >= f) {
                sum -= ((f * (f-1) / 2)% md * (cnt % md)) % md;
                sum = (sum % md + md) % md;
                sum -= (ll)(((c-f+1) % md) * (e % md)) % md;
                sum = (sum % md + md) % md;
            }
            else {
                sum -= ((c * (c+1) / 2) % md * (cnt % md)) % md;
                sum = (sum % md + md) % md;
            }
            sum = (sum % md + md) % md;
            if (d >= f) {
                sum += ((f * (f-1) / 2) % md) * (cnt % md) % md;
                sum = (sum % md + md) % md;
                sum += (ll)(((d-f+1) % md) * (e % md)) % md;
                sum = (sum % md + md) % md;
            }
            else {
                sum += (((d * (d+1) /2) % md) * (cnt) % md) % md;
                sum = (sum % md + md) % md;
            }
        }
        sum = (sum % md + md) % md;
        ans *= pow(v[i].first, sum, mod);
        ans = (ans % mod + mod) % mod;
    }
    ans = (ans % mod + mod) % mod;
    printf("%lld\n", ans);
    return 0;
}

你可能感兴趣的:(数论)