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

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=abj=cdgcd(xiyj)并对 998244353 {998244353} 998244353取模

输入描述:

一行包含六个整数 a , b , c , d , x , y {a,b,c,d,x,y} abcdxy ( 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(0a,b,c,d3×106,0<x,y109,ab,cd.)

输出描述:

一行包含 ∏ 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=abj=cdgcd(xiyj) 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=p1a1p2a2p3a3......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=q1b1q2b2q3b3......qmbm
我们发现, x i x^i xi y j y^j yj的最大公因数一开始很快的增长,后来便不变了。假设 i < j ii<j,因为当 x , y x,y x,y中指数较小的一个和另一个数两两匹配完之后就只剩下指数较大的那个数了,也就是 y j − i y^{j-i} yji
然后我们发现,前 i − 1 i-1 i1 g c d gcd gcd的值依次递增,所以可以用等差数列来求,后 j − i + 1 j-i+1 ji+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
#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);
}

你可能感兴趣的:(gcd)