【2020年牛客暑假第九场】E题 Groundhog Chasing Death 质因子分解

  • 题意
  • 思路
    • 方法一:先枚举iii再枚举公共质因子
      • Code(286ms)
    • 方法二:先枚举公共质因子再枚举iii和jjj
      • Code (691ms)

传送门: https://ac.nowcoder.com/acm/contest/5674/E

题意


求∏i=ab∏i=cdgcd(xi,yj)mod998244353的值求\prod_{i=a}^b\prod_{i=c}^dgcd(x^i, y^j) mod998244353的值求∏i=ab​∏i=cd​gcd(xi,yj)mod998244353的值

思路

观察上式,我们知道gcdgcdgcd是x,yx,yx,y的所有质因子个数的min(a,b)min(a,b)min(a,b),即gcd(x,y)=∑i=1npimin(ai,bi)(ai,bi分别是x,y公共质因子的次幂)gcd(x,y)=\sum_{i=1}^np_i^{min(ai,bi)}(ai,bi分别是x,y公共质因子的次幂)gcd(x,y)=i=1∑n​pimin(ai,bi)​(ai,bi分别是x,y公共质因子的次幂)
所以,我们可以统计x,yx,yx,y的每个公共质因子的次幂,然后再全部整合累乘得出答案。

一步一步分析:
要求∏i=ab∏i=cdgcd(xi,yj)要求\prod_{i=a}^b \prod_{i=c}^dgcd(x^i, y^j)要求∏i=ab​∏i=cd​gcd(xi,yj)
其实求的就是∏p∣x,p∣ypk∑i=ab∑j=cdmin(Ai,Bj)(A,B分别为x,y分解出质因子p的次幂)其实求的就是\prod_{p|x ,p|y}p_k^{\sum_{i=a}^{b}\sum_{j=c}^dmin(Ai,Bj)}(A,B分别为x,y分解出质因子p的次幂)其实求的就是∏p∣x,p∣y​pk∑i=ab​∑j=cd​min(Ai,Bj)​(A,B分别为x,y分解出质因子p的次幂)
先统计x,y所有的公共质因子的次幂,然后再累乘即可先统计x,y所有的公共质因子的次幂,然后再累乘即可先统计x,y所有的公共质因子的次幂,然后再累乘即可
所以我们可以先质数筛把1e9以内的所有质数筛出来,所以范围我定为2e5以内的质数了,然后再分解x和y的质因子,分别把公共质因子p和该因子的次幂cx,cy存在数组里,方便下面步骤的实现所以我们可以先质数筛把\sqrt{1e9}以内的所有质数筛出来,所以范围我定为2e5以内的质数了,然后再分解x和y的质因子,分别把公共质因子p和该因子的次幂cx,cy存在数组里,方便下面步骤的实现所以我们可以先质数筛把1e9​以内的所有质数筛出来,所以范围我定为2e5以内的质数了,然后再分解x和y的质因子,分别把公共质因子p和该因子的次幂cx,cy存在数组里,方便下面步骤的实现
然后单独分析单个公共质因子p,得p∑i=ab∑j=cdmin(Ai,Bj)然后单独分析单个公共质因子p,得p^{\sum_{i=a}^b\sum_{j=c}^d min(Ai,Bj)}然后单独分析单个公共质因子p,得p∑i=ab​∑j=cd​min(Ai,Bj)
先比较Ai和Bj的大小:先比较Ai和Bj的大小:先比较Ai和Bj的大小:
当Ai≤Bj时,即j≥⌈AiB⌉,pmin(Ai,Bj)=pAi\qquad当Ai \leq Bj时,即j \geq \left \lceil \frac{Ai}{B}\right \rceil,p^{min(Ai,Bj)}=p^{Ai}当Ai≤Bj时,即j≥⌈BAi​⌉,pmin(Ai,Bj)=pAi
当Ai>Bj时,即j<⌈AiB⌉,pmin(Ai,Bj)=pBj\qquad当Ai > Bj时,即j < \left \lceil \frac{Ai}{B}\right \rceil,p^{min(Ai,Bj)}=p^{Bj}当Ai>Bj时,即j<⌈BAi​⌉,pmin(Ai,Bj)=pBj

接下来就有两种求解方式了,实质上是一种,只不过枚举顺序有点变化而已。

方法一:先枚举iii再枚举公共质因子

这个方法有点一小麻烦,理解有点困难。

因为先把iii确定下来之后,jjj也就确定下来了,因为j=⌈AiB⌉j= \left \lceil \frac{Ai}{B}\right \rceilj=⌈BAi​⌉。
再来看这个式子:∑i=ab∑j=cdmin(Ai,Bj)\sum_{i=a}^{b}\sum_{j=c}^dmin(Ai,Bj)∑i=ab​∑j=cd​min(Ai,Bj)
因为枚举的是iii,并且jjj已经确定了,再根据大小比较,所以上面的式子就是两种变化:∑i=ab∑j=max(⌈AiB⌉,c)dAi\sum_{i=a}^{b}\sum_{j=max(\left \lceil \frac{Ai}{B}\right \rceil,c)}^dAii=a∑b​j=max(⌈BAi​⌉,c)∑d​Ai
∑i=ab∑j=cdBj\sum_{i=a}^{b}\sum_{j=c}^dBji=a∑b​j=c∑d​Bj
所以就有以下三种情况:
当j<c时,∑i=ab∑j=cdmin(Ai,Bj)=Ai∗(d+c−1)\qquad 当j<c时,\sum_{i=a}^{b}\sum_{j=c}^dmin(Ai,Bj)=Ai*(d+c-1)当j<c时,∑i=ab​∑j=cd​min(Ai,Bj)=Ai∗(d+c−1)

当j>d时,∑i=ab∑j=cdmin(Ai,Bj)=B∗(c+d)∗(d−c+1)2\qquad 当j>d时,\sum_{i=a}^{b}\sum_{j=c}^dmin(Ai,Bj)=B*\frac{(c+d)*(d-c+1)}{2}当j>d时,∑i=ab​∑j=cd​min(Ai,Bj)=B∗2(c+d)∗(d−c+1)​

当c≤j≤d时,∑i=ab∑j=cdmin(Ai,Bj)=Ai∗(d−j+1)+B∗(j+c−1)∗(j−c)2\qquad 当c\leq j \leq d时,\sum_{i=a}^{b}\sum_{j=c}^dmin(Ai,Bj)=Ai*(d-j+1)+B*\frac{(j+c-1)*(j-c)}{2}当c≤j≤d时,∑i=ab​∑j=cd​min(Ai,Bj)=Ai∗(d−j+1)+B∗2(j+c−1)∗(j−c)​

当把所有的公共质因子的总次幂求出来之后就可以进行累乘得出答案,再求总次幂的过程中可以用欧拉降幂优化一下, 并且模数998244353998244353998244353正好是一个质数,所以φ(998244353)=998244353−1\varphi(998244353)=998244353-1φ(998244353)=998244353−1。

Code(286ms)

#include <bits/stdc++.h>using namespace std;typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;const int N = 2e5 + 10;int prime[N];
bool is_prime[N];
int cnt = 0;int px[N], cx[N], py[N], cy[N], mx, my; // 是x和y分解的质因子和质因子的次幂和质因子的个数
ll mi[N]; // 求解出来每个质因子的总次幂struct node{int cx, cy;
};vector<node> v1; // x和y的公共质因子的个数
vector<int> v2; // x和y的公共质因子的值void sieve() // 质数筛
{mem(is_prime, true);is_prime[0] = is_prime[1] = false;for(int i = 2;i < N; i++) {if(is_prime[i]){prime[++cnt] = i;for(int j = 1;j <= cnt && i * prime[j] < N; j++) {is_prime[i * prime[j]] = false;if(i % prime[j] == 0)break;}}}
}void Divide(ll n, int *p, int *c, int &m) // 分解质因子
{m = 0;for(int i = 2;i * i <= n; i++) {if(n % i == 0) {p[++m] = i;while(n % i == 0) {c[m]++;n /= i;}}}if(n > 1) {p[++m] = n;c[m] = 1;}
}ll quick_pow(ll a, ll b)
{ll ans = 1;while(b) {if(b & 1) ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;
}void solve() {sieve();ll a, b, c, d, x, y;scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&x,&y);Divide(x, px, cx, mx); // 分解x和y的质因子(值、个数)并存在数组里Divide(y, py, cy, my);int ppx = 1, ppy = 1;while(ppx <= mx && ppy <= my) { // 寻找x和y的公共质因子并存在数组里if(px[ppx] == py[ppy]) {v1.push_back(node{cx[ppx], cy[ppy]});v2.push_back(px[ppx]);ppx++; ppy++;}else if(px[ppx] < py[ppy]) ppx++;else ppy++;}for(int i = a;i <= b; i++) { // 枚举ifor(int k = 0;k < v1.size(); k++) { // 每个质因子的个数A和B// int p = v2[k]; // 提取质因子int ccx = v1[k].cx, ccy = v1[k].cy; // 提取质因子个数int j = (ccx * i + ccy - 1) / ccy; // 本来是ccx*i/ccy,不过要保证向上取整,即+(B-1)/B就可以保证了,或者使用ceil()函数if(j < c) {ll t = 1ll * (d - c + 1);mi[k] = (mi[k] + t * i * ccx) % (mod - 1);}else if(j > d) {ll t = 1ll * (d + c) * (d - c + 1) / 2;mi[k] = (mi[k] + t * ccy) % (mod - 1);}else {ll t1 = 1ll * (d - j + 1);ll t2 = 1ll * (j - c) * (c + j - 1) / 2;mi[k] = (mi[k] + t1 * ccx * i) % (mod - 1);mi[k] = (mi[k] + t2 * ccy) % (mod - 1);}}}ll ans = 1;for(int i = 0;i < v1.size(); i++) {if(mi[i] == 0) continue;ans = ans * quick_pow(v2[i], mi[i]) % mod;}printf("%lld\n",ans);
}signed main() {ios_base::sync_with_stdio(false);//cin.tie(nullptr);//cout.tie(nullptr);
#ifdef FZT_ACM_LOCALfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);signed test_index_for_debug = 1;char acm_local_for_debug = 0;do {if (acm_local_for_debug == '$') exit(0);if (test_index_for_debug > 20)throw runtime_error("Check the stdin!!!");auto start_clock_for_debug = clock();solve();auto end_clock_for_debug = clock();cout << "Test " << test_index_for_debug << " successful" << endl;cerr << "Test " << test_index_for_debug++ << " Run Time: "<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;cout << "--------------------------------------------------" << endl;} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#elsesolve();
#endifreturn 0;
}

方法二:先枚举公共质因子再枚举iii和jjj

这个方法稍微简单一点,便于理解。

根据下面两个两个大小关系,我们可以先通过枚举每个公共质因子,然后两个循环枚举iii和jjj比大小,确定每个质因子的总次幂即可。
当Ai≤Bj时,即j≥⌈AiB⌉,pmin(Ai,Bj)=pAi当Ai \leq Bj时,即j \geq \left \lceil \frac{Ai}{B}\right \rceil,p^{min(Ai,Bj)}=p^{Ai}当Ai≤Bj时,即j≥⌈BAi​⌉,pmin(Ai,Bj)=pAi
当Ai>Bj时,即j<⌈AiB⌉,pmin(Ai,Bj)=pBj当Ai > Bj时,即j < \left \lceil \frac{Ai}{B}\right \rceil,p^{min(Ai,Bj)}=p^{Bj}当Ai>Bj时,即j<⌈BAi​⌉,pmin(Ai,Bj)=pBj

所以我们可以得到下面两个式子求解公共质因子ppp的总次幂:
∑i=ab∑j=max(⌈AiB⌉,c)dAi\sum_{i=a}^{b}\sum_{j=max(\left \lceil \frac{Ai}{B}\right \rceil,c)}^dAii=a∑b​j=max(⌈BAi​⌉,c)∑d​Ai
∑j=cd∑i=max(⌈BjA⌉,a)bBj\sum_{j=c}^{d}\sum_{i=max(\left \lceil \frac{Bj}{A}\right \rceil,a)}^bBjj=c∑d​i=max(⌈ABj​⌉,a)∑b​Bj

当然,这里有几个小问题。

  • j≥⌈AiB⌉j \geq \left \lceil \frac{Ai}{B}\right \rceilj≥⌈BAi​⌉,如果这里没有正好整除的时候,那还行,因为我们需要的时向上取整,但是如果正好整除呢,那么我们需要j+1j+1j+1即j=AiB+1j=\frac{Ai}{B}+1j=BAi​+1
  • 举一个小栗子,枚举iii的时候,因为j=max(⌈AiB⌉,c)j=max(\left \lceil \frac{Ai}{B}\right \rceil,c)j=max(⌈BAi​⌉,c),要是j>dj>dj>d,那么就不进行下面的操作,同理枚举jjj。

每处理一个公共质因子,把他的总次幂求解出来之后,即可将他用快速幂并加到答案ansansans里,因为可以用到欧拉降幂,所以快速幂之前的pow1+pow2pow1+pow2pow1+pow2先modmodmod就不是998244353998244353998244353,而是998244353−1998244353-1998244353−1,不然会出错的。

Code (691ms)

#include <bits/stdc++.h>using namespace std;typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)const ll mod = 998244353;
// const int maxn = 1e5 + 10;
// const double eps = 1e-6;const int N = 2e5 + 10;int prime[N];
bool is_prime[N];
int cnt = 0;int px[N], cx[N], py[N], cy[N], mx, my; // 是x和y分解的质因子和质因子的次幂和质因子的个数struct node{int cx, cy;
};vector<node> v1; // x和y的公共质因子的个数
vector<int> v2; // x和y的公共质因子的值void sieve() // 质数筛
{mem(is_prime, true);is_prime[0] = is_prime[1] = false;for(int i = 2;i < N; i++) {if(is_prime[i]){prime[++cnt] = i;for(int j = 1;j <= cnt && i * prime[j] < N; j++) {is_prime[i * prime[j]] = false;if(i % prime[j] == 0)break;}}}
}void Divide(ll n, int *p, int *c, int &m) // 分解质因子
{m = 0;for(int i = 2;i * i <= n; i++) {if(n % i == 0) {p[++m] = i;while(n % i == 0) {c[m]++;n /= i;}}}if(n > 1) {p[++m] = n;c[m] = 1;}
}ll quick_pow(ll a, ll b)
{ll ans = 1;while(b) {if(b & 1) ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;
}void solve() {sieve();ll a, b, c, d, x, y;scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&x,&y);Divide(x, px, cx, mx); // 分解x和y的质因子(值、个数)并存在数组里Divide(y, py, cy, my);int ppx = 1, ppy = 1;while(ppx <= mx && ppy <= my) { // 寻找x和y的公共质因子并存在数组里if(px[ppx] == py[ppy]) {v1.push_back(node{cx[ppx], cy[ppy]});v2.push_back(px[ppx]);ppx++; ppy++;}else if(px[ppx] < py[ppy]) ppx++;else ppy++;}ll ans = 1;for(int k = 0;k < v2.size(); k++) { // 枚举每个公共质因子ll pow1 = 0, pow2 = 0; // 下面两个循环的次幂for(ll i = a;i <= b; i++) { // 先枚举ill j;if(v1[k].cx * i % v1[k].cy == 0)j = max(v1[k].cx * i / v1[k].cy, c);elsej = max(v1[k].cx * i / v1[k].cy + 1, c); // 向上取整并且没有整除if(j <= d)pow1 = (pow1 + i * (d - j + 1) % (mod - 1)) % (mod - 1); // 欧拉降幂}pow1 = pow1 * v1[k].cx % (mod - 1); // 不要忘了系数for(ll j = c;j <= d; j++) { // 再枚举jll i = max(v1[k].cy * j / v1[k].cx + 1, a);// 因为上面枚举i的时候处理一次重复的情况,所以这里就不需要再考虑了if(i <= b)pow2 = (pow2 + j * (b - i + 1) % (mod - 1)) % (mod - 1); // 欧拉降幂}pow2 = pow2 * v1[k].cy % (mod - 1); // 不要忘了系数ans = ans * quick_pow(v2[k], (pow1 + pow2) % (mod - 1)) % mod;}printf("%lld\n",ans);
}signed main() {ios_base::sync_with_stdio(false);//cin.tie(nullptr);//cout.tie(nullptr);
#ifdef FZT_ACM_LOCALfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);signed test_index_for_debug = 1;char acm_local_for_debug = 0;do {if (acm_local_for_debug == '$') exit(0);if (test_index_for_debug > 20)throw runtime_error("Check the stdin!!!");auto start_clock_for_debug = clock();solve();auto end_clock_for_debug = clock();cout << "Test " << test_index_for_debug << " successful" << endl;cerr << "Test " << test_index_for_debug++ << " Run Time: "<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;cout << "--------------------------------------------------" << endl;} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#elsesolve();
#endifreturn 0;
}

感谢赛中和赛后牌王的“热情”指导,牌王无敌!!!

【2020年牛客暑假第九场】E题 Groundhog Chasing Death相关推荐

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

    题意 计算 ∏ i = a b ∏ j = c d g c d ( x i , y j ) \prod_{i=a}^{b}\prod_{j=c}^{d}gcd(x^i,y^j) i=a∏b​j=c∏d ...

  2. 【2020年牛客暑假第八场】E题 Enigmatic Partition

    [2020年牛客暑假第八场]E题 Enigmatic Partition 一阶差分+隔项差分 题意 思路 方法一 方法二 Code 反思 题目链接: https://ac.nowcoder.com/a ...

  3. CDMA(牛客第八场构造题)

    链接:https://ac.nowcoder.com/acm/contest/888/C 来源:牛客网 Gromah and LZR have entered the third level. The ...

  4. 2018牛客暑假多校A题GPA 01分数规划

    链接:https://www.nowcoder.com/acm/contest/143/A 来源:牛客网 gpa 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语 ...

  5. 牛客网第九场多校联赛 E Music Game

    题目链接:https://www.nowcoder.com/acm/contest/147/E 题目大意:给出长度为n的序列a,表示每个点成功的概率,从1到n的分数计算方法是,若成功则获得连续成功的长 ...

  6. 2019牛客第四场I题 string

    链接:https://ac.nowcoder.com/acm/contest/884/I 题意:求string串有多少个本质不同的子串,且这些子串之间两两不存在 a==rev(a),即不存在长度1以上 ...

  7. E Groundhog Chasing Death(2020牛客暑期多校训练营(第九场))(思维+费马小定理+质因子分解)

    E Groundhog Chasing Death(2020牛客暑期多校训练营(第九场))(思维+费马小定理+质因子分解) 链接:https://ac.nowcoder.com/acm/contest ...

  8. 2021牛客暑假多校第二场 K题—Stack (链表)

    2021牛客暑假多校第二场 K题-Stack 题意: 一个单调栈,给你第n次操作时里面数据的数量,让你给出里面塞入的会是哪些数字. 主要思想:链表模拟 (代码里面有注释) (题解一开始说的是拓扑,后来 ...

  9. 2021牛客暑假多校第八场 K题—Yet Another Problem About Pi

    2021牛客暑假多校第八场 K题-Yet Another Problem About Pi 题意:告诉你一个单元格的长和宽,问你走Π(3.1415926-)的长度距离最多可以走几个单元格 思路:沿着单 ...

最新文章

  1. netty初探(2)
  2. 客户端界面实现及登录功能实现
  3. 【分析】在线交易开启跨境电商B2B新纪元
  4. There is no getter for property named ‘col‘ in ‘class String‘,不是说一个参数不需要@Param注解吗?#{}和${}的区别
  5. python实现图的数据存储_Neo4j推出基于Python的嵌入式图数据存储
  6. 分别用matlab和python计算物品相似度矩阵(Jaccard系数
  7. .network 中文文档_以太坊链下支付网络Raiden API中文文档
  8. 【Python】Numpy处理.csv数据
  9. C#设计模式之14-命令模式
  10. futuretask java 并发请求_Java并发案例04---Future和 FutureTask
  11. 成也萧何,败也萧何---PIG JOIN 的replicated
  12. 音乐节拍自动标记插件 BeatEdit 2 for Pr
  13. 【linux内核分析与应用-陈莉君】设备驱动模型
  14. 功能测试 —— TPShop商城项目
  15. oracle全局索引改成本地索引,解析一个通过添加本地分区索引提高SQL性能的案例...
  16. DHCP V6 server配置
  17. Virtualbox虚拟机安装win10系统卡顿
  18. 关闭惠普计算机通电启动注册表,惠普电脑自动重启的解决方法
  19. 2023年跨境电商趋势走向,跟随大势迎难而上!
  20. Quartz相关配置

热门文章

  1. 高并发之深度解析CAS [理论+案例+源码]
  2. 解决UNITY3D导入模型贴图材质丢失
  3. 微信小程序wx.login()、wx.getSetting、wx.getUserInfo的区别和联系?
  4. idea中的项目名不见了,只剩下文件及模块如何处理
  5. 二叉树树叶统计算法详解
  6. cms 和 g1的主要区别
  7. 零基础自学python,作为过来人告诉你,这些坑一定要避开......
  8. 2年时间,涨薪20k,想拿高薪还真不能老老实实的工作...
  9. 智慧教学工具在操作系统课程教学中的应用研究
  10. 计算机网络组成原理实验,计算机组成原理实验教程