Groundhog Chasing Death
题目描述:
众所周知,“土拨鼠追逐死亡”的意思是“
G
C
D
GCD
GCD”,而“
G
C
D
GCD
GCD”代表“最大公约数”。
因此,您需要计算
∏
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∏bj=c∏dgcd(xi,yj)并对
998244353
{998244353}
998244353取模
输入描述:
一行包含六个整数 a , b , c , d , x , y {a,b,c,d,x,y} a,b,c,d,x,y ( 0 ⩽ a , b , c , d ⩽ 3 × 1 0 6 , 0 < x , y ⩽ 1 0 9 , a ⩽ b , c ⩽ d . ) (0⩽a,b,c,d⩽3×10^6,0<x,y⩽10^9,a⩽b,c⩽d.) (0⩽a,b,c,d⩽3×106,0<x,y⩽109,a⩽b,c⩽d.)
输出描述:
一行包含 ∏ 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∏bj=c∏dgcd(xi,yj) m o d mod mod 998244353 {998244353} 998244353
样例:
样例输入1:
1 2 1 2 8 4
样例输出1:
2048
样例输入2:
1 2 3 4 120 180
样例输出2:
235140177
思路:
首先看看数据范围(正所谓看数据猜算法 ),发现
O
(
N
2
)
O(N^2)
O(N2)都过不了,只有
O
(
N
l
o
g
N
)
,
O
(
N
)
O(NlogN),O(N)
O(NlogN),O(N)能过。
我们令
x
i
=
p
1
a
1
∗
p
2
a
2
∗
p
3
a
3
∗
.
.
.
.
.
.
p
n
a
n
x^i=p_1^{a1}*p_2^{a2}*p_3^{a3}*......p_n^{an}
xi=p1a1∗p2a2∗p3a3∗......pnan
y
j
=
q
1
b
1
∗
q
2
b
2
∗
q
3
b
3
∗
.
.
.
.
.
.
q
m
b
m
y^j=q_1^{b1}*q_2^{b2}*q_3^{b3}*......q_m^{bm}
yj=q1b1∗q2b2∗q3b3∗......qmbm
我们发现,
x
i
x^i
xi和
y
j
y^j
yj的最大公因数一开始很快的增长,后来便不变了。假设
i
<
j
i<j
i<j,因为当
x
,
y
x,y
x,y中指数较小的一个和另一个数两两匹配完之后就只剩下指数较大的那个数了,也就是
y
j
−
i
y^{j-i}
yj−i。
然后我们发现,前
i
−
1
i-1
i−1个
g
c
d
gcd
gcd的值依次递增,所以可以用等差数列来求,后
j
−
i
+
1
j-i+1
j−i+1个
y
y
y和
x
x
x的最大公因数相同,可以直接计算,如果最后
x
>
1
x>1
x>1,说明
x
x
x和
y
y
y可能还有质因数,再做一遍即可。
时间复杂度
O
(
N
)
O(N)
O(N)
A C AC AC C o d e Code Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=998244353;
ll a,b,c,d,x,y,z,ans=1,n,u,v,md=mod-1;
ll ksm(ll a,ll b){
ll ret=1;
while(b){
if(b&1)ret=ret*a%mod;
a=a*a%mod;
b>>=1;
}
return ret;
}
ll get(ll x,ll y){
ll k=0,p;
for(int i=1;i<=x;i++){
p=u*i/v;
p=min(p,y);
k=(k+(p+1ll)*p/2%md*v)%md;
k=(k+1ll*i*(y-p)%md*u)%md;
}
return k;
}
int main(){
scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&x,&y);
n=max(x,y);
for(int i=2;i*i<=n;i++){
while(x%i==0) u++,x/=i;
while(y%i==0) v++,y/=i;
if(u&&v){
z=(2ll*md+get(b,d)+get(a-1,c-1)-get(a-1,d)-get(b,c-1))%md;
ans=1ll*ans*ksm(i,z)%mod;
}
u=v=0;
}
if(x^0&&x==y){
u=v=1;
z=(2ll*md+get(b,d)+get(a-1,c-1)-get(a-1,d)-get(b,c-1))%md;
ans=1ll*ans*ksm(x,z)%mod;
}
printf("%lld",ans);
}