Educational Codeforces Round 85 (Rated for Div. 2) E Divisor Paths

链接


最短路:x->gcd(x,y)->y
然后就是一个有重复数字的错排问题,
设每种数字分别出现k1,k2,k3…kp次,并假设该错排的答案为f
那么f*k1!*k2!k3!…*kp!= ( sigma(ki) )!

#pragma GCC optimize(2)
#include
#define ls rt<<1
#define rs rt<<1|1
#define pb push_back
#define fi first
#define se second
#define yes puts("YES")
#define no puts("NO")
#define ios ios::sync_with_stdio(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int maxn = 1e6 + 6;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
LL qp(LL x,LL y){LL ans=1;x%=mod;while(y){if(y&1) ans=ans*x%mod;x=x*x%mod;y>>=1;}return ans;}
LL inv(LL x){return qp(x,mod-2);}


//head
vector<LL>x;
LL fac[maxn],fnv[maxn];

LL way(LL u){
   LL f=1,s=0,len=x.size();
   for(int i=0;i<len;i++){
       int p=0;
       while(u%x[i]==0) u/=x[i],p++;
       f=f*fnv[p]%mod;
       s+=p;
   }
   return f*fac[s]%mod;
}

int main(){
    fac[0]=fnv[0]=1;
    for(int i=1;i<=100000;i++) {
        fac[i]=fac[i-1]*i%mod;
        fnv[i]=qp(fac[i],mod-2);
    }

    LL d;scanf("%lld",&d);
    for(LL i=2;i*i<=d;i++){
        if(d%i==0){
            x.pb(i);
            while(d%i==0) d/=i;
        }
    }
    if(d>1) x.pb(d);
    int q;scanf("%d",&q);
    while(q--){
        LL u,v;scanf("%lld%lld",&u,&v);
        LL gcd=__gcd(u,v);
        printf("%lld\n",way(u/gcd)*way(v/gcd)%mod);
    }
}














你可能感兴趣的:(Codeforces)