1334E - Divisor Paths 质因数分解+观察性质

很容易发现,u->v,如果u>v,则u不断通过除以质因子缩小到v,所经路径长度时不变的。

考虑a->b的路径长度,为a有的因子,且b无的因子的个数。

观察a>b.  a->x->b  (a>=x>=b)与a->b  这两条路径。

前者是a有且x无的因子个数,加上x有且b无的因子个数。

显然,x无的因子,b一定也无,x有的因子,a一定也有。

则上述可以改成:a有b无的因子个数。即与a->b的路径长度相同。

有了这个性质这题就简单了。

先让u是大的数。

如果u是v的倍数直接u/v的质因子多重集排列即可。

否则先让v变成x,使得x是u的因子。再让u到v,这样路径最短。

结果是两个多重集排列的乘积。

具体看代码。

#include 
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
const int mod = 998244353 ;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
vectorp,c;
ll fac[100000+7]; 
ll inv[100000+7];
ll qpow(ll a,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b/=2;
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	fac[0]=1;inv[0]=1;
  	for(int i=1;i<=100000;i++)
  		fac[i]=fac[i-1]*i%mod,inv[i]=qpow(fac[i],mod-2);
  	ll D;
	int q;
	cin>>D;
	for(int i=2;i<=sqrt(D);i++)
	{
		if(D==1)break;
		if(D%i==0)
		{
			int z=0;
			while(D%i==0)
			D/=i,z++;
			p.pb(i),c.pb(i);
		//	cout<>q;
	while(q--)
	{
		ll U,V;
		cin>>U>>V;
		if(U==V)
		{
			cout<<1<V)swap(U,V);
		unordered_mapmp;
		vectorp1,p2;
		for(int i=0;imp[p[i]])
				{
					p1.pb(z-mp[p[i]]);
					n1+=z-mp[p[i]];
				}
				else
				{
					p2.pb(mp[p[i]]-z);
					n2+=mp[p[i]]-z;
				}
				mp[p[i]]=0; 
			}
		}
		for(auto x:mp)
		{
			if(x.second==0)continue;
			p2.pb(x.second);n2+=x.second;
		}
		ll ans=fac[n1]*fac[n2]%mod;
		for(int i=0;i

 

你可能感兴趣的:(CF,数学——找规律/数学归纳)