2020牛客暑期多校第九场 E - Groundhog Chasing Death(gcd+质因数分解)

传送门


题目大意:

首先看到 g c d gcd gcd就应该想到 g c d gcd gcd的本质,即质因数分解后对于相同的质因子取 m i n ( p 1 , p 2 ) min(p_1,p_2) min(p1,p2),而且不难发现对 x , y x,y x,y求幂,不会影响质因子的种类,只是会改变指数,而且是以等差数列增长的。显然只需要一次质因数分解记录底数和对应指数,使用map记录相同的质因子以及各自初始对应的个数,然后考虑指数的变化

显然我们只需要遍历 a a a或者 b b b的相同质因子从 a − b a-b ab(或者 c − d c-d cd)的数目作为初始值,然后考虑另一个数在区间对应指数是一个等差数列,只要除以它算出一个商,然后考虑这个商和区间 [ c , d ] [c,d] [c,d]的关系即可,具体细节画图更容易找到

需要注意的是指数会爆long long,使用__int128处理指数即可

#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=998244353;
const int maxn=2e5+10;

ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}

void getPrime(int *fac,int *num,int n,int &cnt){
    int m=sqrt(n+0.5);
    cnt=0;
    for(int i=2;i<=m;i++){
        if(n%i==0){
            fac[cnt]=i;
            while(n%i==0){
                num[cnt]++;
                n/=i;
            }
            cnt++;
        }
        if(n==1) break;
    }
    if(n>1){
        fac[cnt]=n;
        num[cnt++]++;
    }
}

ll qkp(ll x,__int128 n,ll p){
    ll ans=1;
    while(n){
        if(n&1) ans=ans*x%p;
        x=x*x%p;
        n>>=1;
    }
    return ans;
}

int facx[maxn],facy[maxn];
int num1[maxn],num2[maxn];
int cnt1,cnt2;

vector<int> cfac;
vector<int> numx,numy;
unordered_map<int,int> mp;

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int a,b,c,d,x,y;
    cin>>a>>b>>c>>d>>x>>y;
    getPrime(facx,num1,x,cnt1);
    getPrime(facy,num2,y,cnt2);

    for(int i=0;i<cnt1;i++) mp[facx[i]]=1;

    for(int i=0;i<cnt2;i++) if(mp.count(facy[i])){
        cfac.push_back(facy[i]),mp[facy[i]]++;
        numy.push_back(num2[i]);
    }

    for(int i=0;i<cnt1;i++){
        if(mp[facx[i]]>1){
            numx.push_back(num1[i]);
        }
    }

    ll ans=1;
    for(int i=0;i<cfac.size();i++){
        __int128 sum=0;
        for(int j=a;j<=b;j++){
            int p=j*numx[i]/numy[i],q=j*numx[i]%numy[i];
            if(p<c){
                sum+=(__int128)j*numx[i]*(d-c+1);
            }else if(p>=d){
                sum+=(__int128)numy[i]*(c+d)*(d-c+1)/2;
            }else{
                sum+=(__int128)numy[i]*(c+p)*(p-c+1)/2;
                sum+=(__int128)j*numx[i]*(d-p);
            }
        }
        ans=ans%Mod*qkp(cfac[i],sum,Mod)%Mod;
    }
    cout<<ans<<"\n";
    return 0;
}

你可能感兴趣的:(牛客比赛)