2020牛客暑期多校训练营(第九场)- E. 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的大小
当$j\geq \lceil \frac{a*i}{b} \rceil$时有$a*i\leq b*j$,此时$p^{min(a*i,b*j)}=p^{a*i}$
当$j< \lceil \frac{a*i}{b} \rceil$时有$a*i>b*j$,此时$p^{min(a*i,b*j)}=p^{b*j}$
对于每个p,我们可以枚举i,显然$\lceil \frac{a*i}{b} \rceil$时确定的
对于$\geq \lceil \frac{a*i}{b} \rceil$的j来说,p的幂次为$a*i*(d- \lceil \frac{a*i}{b} \rceil +1)$
对于$< \lceil \frac{a*i}{b} \rceil$的j来说,p的幂次为$b*[c+(c+1)+\dots +(\lceil \frac{a*i}{b} \rceil -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\n", res); return 0; }