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

原题
题目描述
2020牛客暑期多校训练营(第九场) Groundhog Chasing Death_第1张图片
样例1
输入

1 2 1 2 8 4

输出

2048

样例2
输入

1 2 3 4 120 180

输出

235140177

思路
首先看数据范围,如果直接枚举 x x xi y y yj,时间复杂度为 3 e 6 × 3 e 6 = 9 e 12 3e6×3e6=9e12 3e6×3e6=9e12 T L E TLE TLE等着你。所以我们要想出 O ( n ) O(n) O(n)的算法。
我们先固定 i i i,然后把 x x xi y y yj ( j : c (j:c (jc~ d ) d) d)分解质因数:
x x xi = = = q 1 q1 q1x1 × × × q 2 q2 q2x2 × × × q 3 q3 q3x3 × × × q 4 q4 q4x4 … … ……
y y yj = = = q 1 q1 q1y1 × × × q 2 q2 q2y2 × × × q 3 q3 q3y3 × × × q 4 q4 q4y4 … … ……
我们可以把他们最大公因数的函数图像画出来,大概是以下这种情况 : :
2020牛客暑期多校训练营(第九场) Groundhog Chasing Death_第2张图片
刚开始 g c d gcd gcd j j j的增加而增加。后来 x x xi的与 y y y每个公共因子 y y yz次方匹配完。所以之后 y y yx y y yd x x xi的最大公因数不变。观察函数图像,我们会知道 : :

  • y y y z − 1 z-1 z1次方与 x x xi的最大公因数递增,可以用等差数列求和。
  • y y y z z z次方与 x x xi的最大公因数不变,直接计算即可。

注意 : : 最后如果 x > 1 x>1 x>1,则表示 x x x y y y可能还有质因数,再计算一次即可。
时间复杂度: O ( n ) O(n) O(n)
代码

#include
#define ll long long
using namespace std;
const ll mod=998244353,md=998244352;
ll a,b,c,d,x,y,z,ans=1,n,u,v;
ll ksm(ll a,ll b)
{
	ll c=1;
	while(b)
	{
		if(b&1)c=c*a%mod;
		a=a*a%mod;b>>=1;
	}
	return c;
}
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++,u=0,v=0)
	{
		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;
	}
	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);
	return 0;
}

你可能感兴趣的:(2020牛客暑期多校训练营(第九场) Groundhog Chasing Death)