E_Groundhog Chasing Death(不错的数论)

文章目录

  • [题目链接:E_Groundhog Chasing Death](https://ac.nowcoder.com/acm/contest/5674/E)
    • 题目大意
    • 解题思路
    • 代码

题目链接:E_Groundhog Chasing Death

题目大意

这一道裸的数论题,题意就不省略了。

解题思路

我们可以对 x 和 y x和y xy 进行质因子分解,经过化简我们可以得到下面这个公式
p ∑ i = a b ∑ j = c d m i n ( i ∗ n , j ∗ m ) p^{\sum_{i=a}^{b} \sum_{j=c}^{d} min(i*n,j*m)} pi=abj=cdmin(in,jm)
其 中 p 为 x 和 y 的 公 共 质 因 子 个 数 , n 和 m 分 别 表 示 x 和 y 中 分 别 有 几 个 其中p为x和y的公共质因子个数,n和m分别表示x和y中分别有几个 pxynmxy
其中对于统计指数的个数的时候可以根据 n ∗ i n*i ni 的大小去处理 m m m
很明显只有存在相同质因子的时候需要统计下该质因子的指数就可以。
注意的是根据费马小定理对指数取模的时候应该是   % ( m o d − 1 ) \ \%(mod-1)  %mod1

代码

/*

*/
#include
using namespace std;
#define ll long long
const ll mx=2000100;
const ll mod=998244353;
map<int,ll>mp;
ll a,b,c,d,ans=1;
ll poow(ll A,ll B){
	ll res=1;
	while(B){
		if(B&1) res=res*A%mod;
		A=A%mod*A%mod;
		B>>=1;
	}
	return res%mod;
}
// x表示 x中p的个数 y表示y中p的个数 
void ji_suan(ll x,ll y,ll p){
	ll sum=0;
	ll cnt;
	for(ll i=a;i<=b;i++){
		ll tem=x*i;
// 确定多少个 y以内 都是 现在的 x*i 大,
// 到时候只用求 关于 y 的前 ty 项和就可以		
		ll ty=tem/y; 
		ll flag=0;
		cnt=0;
// 如果 ty 小于 c 说明求和的时候 一直都是 x*i 小 		
		if(ty<c) flag=1; 
		if(ty>=c){
		// 计算 ty 的前 n 项和
		// 为了防止 ty 大于 d 的情况需要取两者的最小值	
			ll bb=min(ty,d);	
			cnt=y*(c+bb)*(bb-c+1)/2%(mod-1);
		}
		// 记录指数的个数 
		sum=(sum+cnt)%(mod-1);
		cnt=0;
		if(ty<=d){
	// 这里为了防止 ty 下于 c	所以去最大值	
			ty=max(ty,c);
			cnt=tem*(d-ty+flag)%(mod-1);
			sum=(sum+cnt)%(mod-1);	
		}
	}
	// 记录答案 
	ans=ans*poow(p,sum)%mod; 
}
int main(){	
	ios::sync_with_stdio(0);
	ll x,y;
	cin>>a>>b>>c>>d>>x>>y;
	//先对 x 进行质因子分解并且记录每个质因子的个数 
	for(ll i=2;i*i<=x;i++){
		while(x%i==0){
			mp[i]++;
			x/=i;
		}
	}
	if(x!=1) mp[x]++;
	
	int num;bool f;
	for(ll i=2;i*i<=y;i++){
		num=0;
		f=0;
		if(y%i==0) f=1;
		while(y%i==0){
			num++;
			y/=i;
		}
// 对 y 进行质因子分解,如果有相同的因子的话
// 就进行判断。		
		if(mp[i]&&f){
			ji_suan(mp[i],num,i);
		}
	}
	if(y!=1&&mp[y]){
		ji_suan(mp[y],1,y);
	}
	cout<<ans<<"\n";
    return 0;
}

你可能感兴趣的:(牛客,数学)