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

原题
题目描述
在这里插入图片描述
样例1
输入

1 2 1 2 8 4

输出

2048

样例2
输入

1 2 3 4 120 180

输出

235140177

思路
首先看数据范围,如果直接枚举 x x i y y j,时间复杂度为 3 e 6 × 3 e 6 = 9 e 12 3e6×3e6=9e12 T L E TLE 等着你。所以我们要想出 O ( n ) O(n) 的算法。
我们先固定 i i ,然后把 x x i y y j ( j c (j:c ~ d ) d) 分解质因数:
x x i = = q 1 q1 x1 × × q 2 q2 x2 × × q 3 q3 x3 × × q 4 q4 x4 ……
y y j = = q 1 q1 y1 × × q 2 q2 y2 × × q 3 q3 y3 × × q 4 q4 y4 ……
我们可以把他们最大公因数的函数图像画出来,大概是以下这种情况
在这里插入图片描述
刚开始 g c d gcd j j 的增加而增加。后来 x x i的与 y y 每个公共因子 y y z次方匹配完。所以之后 y y x y y d x x i的最大公因数不变。观察函数图像,我们会知道

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

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

#include<bits/stdc++.h>
#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;
}

猜你喜欢

转载自blog.csdn.net/bbbll123/article/details/107892610
今日推荐