• 2020牛客暑期多校训练营(第九场)- E. Groundhog Chasing Death


    题目链接:Groundhog Chasing Death

    题意:给你一个a,b,c,d,x,y,求$prod_{i=a}^{b} prod_{j=c}^{d} gcd(x^i,y^j)$的值

    思路:对x,y质因数分解,对于x和y的某一个公共质因子p,假设x分解后p的幂次为a,y分解后p的幂次位为b,当i,j确定时,p对答案贡献为$p^{min(a*i,b*j)}$,接下来考虑一下a*i和b*j的大小

    当$jgeq lceil frac{a*i}{b} ceil$时有$a*ileq b*j$,此时$p^{min(a*i,b*j)}=p^{a*i}$

    当$j< lceil frac{a*i}{b} ceil$时有$a*i>b*j$,此时$p^{min(a*i,b*j)}=p^{b*j}$

    对于每个p,我们可以枚举i,显然$lceil frac{a*i}{b} ceil$时确定的

    对于$geq lceil frac{a*i}{b} ceil$的j来说,p的幂次为$a*i*(d- lceil frac{a*i}{b} ceil +1)$

    对于$< lceil frac{a*i}{b} ceil$的j来说,p的幂次为$b*[c+(c+1)+dots +(lceil frac{a*i}{b} ceil -1)]$

    算出每个p的总的幂次(幂次加的过程中需要欧拉降幂),然后快速幂求解即可

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <vector>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 3000010;
    const ll mod = 998244353;
    
    struct node {
        int a, b;
        node() { }
        node(int ta, int tb) : a(ta), b(tb) { }
    };
    
    int a, b, c, d, x, y;
    int px[N], cx[N], py[N], cy[N], mx, my;
    vector<node> v;
    vector<int> alls;
    ll mi[N];
    
    void divide(int n, int *p, int *c, int &m)
    {
        m = 0;
        for (int i = 2; i <= sqrt(n); i++) {
            if (0 != n % i) continue;
            p[++m] = i;
            c[m] = 0;
            while (0 == n % i) {
                n /= i;
                c[m] += 1;
            }
        }
        if (n > 1) {
            p[++m] = n;
            c[m] = 1;
        }
    }
    
    ll power(ll a, ll n)
    {
        ll res = 1;
        while (n) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }
    
    int get_id(int x)
    {
        return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;
    }
    
    int main()
    {
        // freopen("in.txt", "r", stdin);
        // freopen("out.txt", "w", stdout);
        scanf("%d%d%d%d%d%d", &a, &b, &c, &d, &x, &y);
        divide(x, px, cx, mx);
        divide(y, py, cy, my);
        int ppx = 1, ppy = 1;
        while (ppx <= mx && ppy <= my) {
            if (px[ppx] == py[ppy]) {
                v.push_back(node(cx[ppx], cy[ppy]));
                alls.push_back(px[ppx]);
                ppx += 1;
                ppy += 1;
            }
            else if (px[ppx] < py[ppy]) ppx += 1;
            else ppy += 1;
        }
        for (int i = a; i <= b; i++) {
            for (int k = 0; k < v.size(); k++) {
                int mia = v[k].a, mib = v[k].b, id = get_id(alls[k]);
                int j = (i * mia + mib - 1) / mib;
                if (j > d) {
                    ll t = 1ll * (c + d) * (d - c + 1) / 2;
                    mi[id] = (mi[id] + t * mib) % (mod - 1);
                }
                else if (j < c) {
                    ll t = d - c + 1;
                    mi[id] = (mi[id] + t * mia * i) % (mod - 1);
                }
                else {
                    ll ta = 1ll * (c + j - 1) * (j - c) / 2, tb = d - j + 1;
                    mi[id] = (mi[id] + ta * mib) % (mod - 1);
                    mi[id] = (mi[id] + tb * mia * i) % (mod - 1);
                }
            }
        }
        ll res = 1;
        for (int i = 1; i <= alls.size(); i++) {
            if (0 == mi[i]) continue;
            ll t = power(alls[i - 1], mi[i]);
            res = res * t % mod;
        }
        printf("%lld
    ", res);
        return 0;
    }
  • 相关阅读:
    python之enumerate
    Python中的集合set
    SGU 分类
    太空飞行计划 最大权闭合图
    1.飞行员配对 二分图匹配(输出方案)/最大流斩
    poj1149最大流经典构图神题
    hdu1569 方格取数 求最大点权独立集
    最大独立集 最小点覆盖 最小边覆盖 最小路径覆盖 最大团
    hdu3491最小割转最大流+拆点
    hdu3987,最小割时求最少割边数
  • 原文地址:https://www.cnblogs.com/zzzzzzy/p/13458306.html
Copyright © 2020-2023  润新知