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

链接:https://ac.nowcoder.com/acm/contest/5674/E
来源:牛客网

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

As we all know,“Groundhog chasing death” means “GCD”,while “GCD” stands for “greatest common divisor”.

So you need to calculate ∏ i = a b ∏ j = c d gcd ⁡ ( x i , y j ) \displaystyle\prod_{i=a}^b\prod_{j=c}^d\gcd(x^i,y^j) i=a∏b​j=c∏d​gcd(xi,yj) modulo 998244353 {998244353} 998244353.

输入描述:

One line which contains six intergers a , b , c , d , x , y {a,b,c,d,x,y} a,b,c,d,x,y.

输出描述:

One line which contains
∏ i = a b ∏ j = c d gcd ⁡ ( x i , y j ) \displaystyle\prod_{i=a}^b\prod_{j=c}^d\gcd(x^i,y^j) i=a∏b​j=c∏d​gcd(xi,yj) modulo 998244353 {998244353} 998244353.

示例1

输入

1 2 1 2 8 4

输出

2048

示例2

输入

1 2 3 4 120 180

输出

235140177

备注:

0 ⩽ a , b , c , d ⩽ 3 × 1 0 6 , 0 < x , y ⩽ 1 0 9 , a ⩽ b , c ⩽ d 0\leqslant{a,b,c,d\leqslant 3\times10^6,0<x,y\leqslant10^9},a\leqslant b,c\leqslant d 0⩽a,b,c,d⩽3×106,0<x,y⩽109,a⩽b,c⩽d.

题意

给出 a , b , c , d , x , y a,b,c,d,x,y a,b,c,d,x,y,让求出 ∏ i = a b ∏ j = c d gcd ⁡ ( x i , y j ) \displaystyle\prod_{i=a}^b\prod_{j=c}^d\gcd(x^i,y^j) i=a∏b​j=c∏d​gcd(xi,yj)。

题解

暴力做法:枚举 i i i和 j j j,算出 x i x^i xi和 y j y^j yj求乘积。注意求幂的时候不能取模,因为取模后最大公约数就变了。时间复杂度 O ( n 2 l o g n ) O(n^2logn) O(n2logn),既会爆long long,又会超时。

改进做法:考虑 x x x和 y y y的公共素因子,取 i i i次方和 j j j次方就相当于把素因子的个数变为 i i i倍或 j j j倍。这样的话每次枚举时更新因子个数,枚举结束后再把各个素因子乘起来,乘的时候可以取模。时间复杂度 O ( n 2 l o g n ) O(n^2logn) O(n2logn)。会超时但不会爆long long了。

继续改进:考虑到枚举过程中 x x x和 y y y的值是不变的,所以预处理出 x x x和 y y y的公共素因子,并求出每个素因子分别在 x x x和 y y y中出现的次数,那么 x i x^i xi就相当于把x中的素因子个数都变成 i i i倍, y j y^j yj同理。

把 x x x和 y y y中每个素因子的个数分开考虑,因为题目要求的是求所有gcd的乘积,所以我们把用于构建gcd的素因子的个数直接加起来即可。

发现每枚举一个 i i i,对应的连续的 j j j存在线性关系:当 j j j比较小的时候, x i x^i xi和 y j y^j yj的最大公约数的限制主要体现在 y y y的素因子个数上。 j j j不断增加, y y y中的素因子个数就变成了一个个等差数列。可以利用等差数列求和公式 O ( 1 ) O(1) O(1)算出这一段区间的 j j j对 y y y的素因子个数的贡献,而当 y y y比较大时,gcd的限制主要体现在 x x x的素因子个数上,那么不论 j j j再怎么增加, i i i不变,那么构建出来的gcd的值就不会变,此时后一半区间的 y y y对素因子的贡献就是 x x x中素因子出现的个数乘以这一段 y y y的区间长度。

注意枚举的时候不要直接计算出素因子的幂,不然会超时。先保存每个素因子的总个数,之后再求幂和乘积。注意直接保存素因子的总个数会爆long long。需要利用费马小定理: a ( p − 1 ) ≡ 1 ( m o d p ) a^{(p-1)}≡1(mod\ p) a(p−1)≡1(mod p),把素因子的个数对“mod-1”取模即可。时间复杂度 O ( n l o g n ) O(n\ log n) O(n logn)

最后利用快速幂算出每个幂的值,然后求乘积即可。

代码

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define _for(i, a) for(register int i = 0, lennn = (a); i < lennn; ++i)
#define _rep(i, a, b) for(register int i = (a), lennn = (b); i <= lennn; ++i)
#define scl(x) scanf("%lld", &x)
using namespace std;
typedef long long LL;
const int mod = 998244353;
int debug = 0;LL a, b, c, d, x, y;
vector<LL> gcdd, gnumx, gnumy, mi;  //gcdd保存x和y的公共素因子,gnumx保存x中每个公共素因子的个数,gnumy保存y中每个公共素因子的个数,mi保存最终答案中每个公共素因子的个数。inline void init() {gcdd.clear();gnumx.clear();gnumy.clear();mi.clear();
}struct Prime {vector<int> arr;int vis[100006];void doit(int maxnum) {for(int i = 2; i <= maxnum; ++i) {if(!vis[i]) arr.push_back(i);for(int j = 0; j < arr.size() && arr[j] * i <= maxnum; ++j) {vis[arr[j] * i] = 1;if(i % arr[j] == 0) break;}}}
}P;inline LL quickPow(LL x, LL n) {LL ans = 1;while(n) {if(n & 1) ans *= x, ans %= mod;x *= x, x %= mod;n >>= 1;}return ans;
}inline void sol() {init();LL g = __gcd(x, y);for(int i = 0; P.arr[i] * P.arr[i] <= g; ++i) { //把x和y的最大公约数分解,把素因子存起来if(g % P.arr[i] == 0) {gcdd.push_back(P.arr[i]);while(g % P.arr[i] == 0) g /= P.arr[i];}}if(g > 1) gcdd.push_back(g);mi.resize(gcdd.size());fill(mi.begin(), mi.end(), 0);LL tx = x, ty = y;for(auto &i : gcdd) {       //求出每个素因子在x和y中出现的次数gnumx.push_back(0);while(tx % i == 0) {++gnumx.back();tx /= i;}gnumy.push_back(0);while(ty % i == 0) {++gnumy.back();ty /= i;}}if(debug) {_for(i, gcdd.size()) {printf("%d: x %d, y %d\n", gcdd[i], gnumx[i], gnumy[i]);}}LL ans = 1;_rep(i, a, b) {             //枚举每一个i,计算j的贡献_for(x, gcdd.size()) {LL numx = 0;LL num = gnumx[x] * i;LL m = num / gnumy[x];if(m >= c) {        //gcd的值主要被y的素因子个数所限制,等差数列求和LL r = min(m, d);numx += gnumy[x] * (r + c) * (r - c + 1) / 2;}if(d > m) {         //gcd的值主要被x的素因子个数所限制,此时j的贡献是一段恒定的值LL l = max(m + 1, c);numx += num * (d - l + 1);}mi[x] += numx;mi[x] %= (mod - 1);//费马小定理}}_for(i, gcdd.size()) {ans = ans * quickPow(gcdd[i], mi[i]) % mod;}printf("%lld\n", ans);
}int main() {//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#elsefreopen("in.txt", "r", stdin);debug = 1;
#endiftime_t beg, end;if(debug) beg = clock();P.doit(100000);while(~scl(a)) {scl(b), scl(c), scl(d), scl(x), scl(y);sol();}if(debug) {end = clock();printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);}return 0;
}/*
in:
0 3000000 0 3000000
223092870
223092870out:
824590783*/

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

  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牛客暑期多校训练营(第六场)

    2020牛客暑期多校训练营(第六场) 额,睡了一下午,直接错过了比赛... 文章目录 A African Sort 题意: 题解: 代码: B Binary Vector C Combination ...

  3. 2020牛客暑期多校训练营(第四场)

    2020牛客暑期多校训练营(第四场) 这场属实有点难受 文章目录 A Ancient Distance B Basic Gcd Problem 题目 代码: C Count New String D ...

  4. 2020牛客暑期多校训练营(第一场)

    文章目录 A B-Suffix Array B Infinite Tree C Domino D Quadratic Form E Counting Spanning Trees F Infinite ...

  5. 2020牛客暑期多校训练营(第二场)

    2020牛客暑期多校训练营(第二场) 最烦英语题 文章目录 A All with Pairs B Boundary C Cover the Tree D Duration E Exclusive OR ...

  6. 2020牛客暑期多校训练营(第七场)J.Pointer Analysis

    2020牛客暑期多校训练营(第七场)J.Pointer Analysis 题目链接 题目描述 Pointer analysis, which aims to figure out which obje ...

  7. 2020牛客暑期多校训练营(第三场)A.Clam and Fish

    2020牛客暑期多校训练营(第三场)A.Clam and Fish 题目链接 题目描述 There is a fishing game as following: The game contains ...

  8. 2020牛客暑期多校训练营(第五场)——E Bogo Sort

    2020牛客暑期多校训练营(第五场)--E Bogo Sort 题目描述 Today Tonnnny the monkey learned a new algorithm called Bogo So ...

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

    Groundhog Chasing Death 题意:给出a.b.c.d.x.y,让求下列式子. 思路:对于gcd(x,y)我们知道 gcd(x,y)=p1 ^(min(n1,n2)) * p2 ^( ...

最新文章

  1. Python开发(基础):字符串
  2. Express踩坑系列之上传文件
  3. weboffice 应用
  4. 8个容易被忽略但不能忽略的SD-WAN功能-Vecloud
  5. LeetCode-剑指 Offer 18. 删除链表的节点
  6. mysql每一步花费时间_MySQL花费更多时间发送数据
  7. C语言 十进制整数字符串转十六进制字符串
  8. 用计算机演奏打上花火,米津玄师打上花火歌词中文谐音(最好要简单全面)
  9. java中start与loop_java for-loop问题
  10. React文档(十九)不使用ES6
  11. 重做《机房收费系统》——概要设计(UI)
  12. Java 数据结构之双链表
  13. linux cmake 快速安装
  14. MacOS:Shell工具-Royal TSX
  15. python中def demo是什么意思_Python def函数的定义、使用及参数传递实现代码
  16. 新媒体运营数据分析怎么做?
  17. Url短连接实现原理与方法
  18. Java学习(84)Java集合——案例:公告管理(ArrayList增删改查)
  19. all boot options are tried的问题解决
  20. 细菌(disease)解题报告 - 搜索与回朔

热门文章

  1. InternetOpen怎么使用代理
  2. 6种方法,打造精彩开头和结尾
  3. 2017年第三届 美亚杯电子取证 团体赛 wp
  4. 支持轴体热插拔的平价机械键盘,全尺寸带灯效,雷柏V700DIY上手
  5. 电竞真无线悦自由,HyperX极度未知云雀TWS电竞游戏真无线耳机
  6. 【clumsy】带宽限制模块 bandwidthModule
  7. 网络创业8年 接下来这条路该怎么走?
  8. React中使用ref
  9. 随笔一计:微信h5支付商家存在未配置的参数xxx
  10. vue中的template标签