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 (j:c~ 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 … … …… ……
我们可以把他们最大公因数的函数图像画出来,大概是以下这种情况 : : :
刚开始 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的最大公因数不变。观察函数图像,我们会知道 : : :
注意 : : :最后如果 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;
}