JZOJ 5970 space

Space

Description

一个四维空间中有 n 4 n^4 n4个点,每个点的每一维坐标都是整数,范围为 [ 1 , n ] [1,n] [1,n],接着给出四个 n n n的排列 A , B , C , D A,B,C,D ABCD,一开始在 ( 1 , 1 , 1 , 1 ) (1,1,1,1) (1,1,1,1)点,现在要遍历四维空间中所有的点,假设当前在点 ( x , y , z , h ) (x,y,z,h) (x,y,z,h),则从这个点去到 ( A x , B y , C z , D h ) (A_x,B_y,C_z,D_h) (Ax,By,Cz,Dh)的代价为 1 1 1,否则为 2 2 2,求总代价最小的便利方案,求最小代价。

Data Constraints

n ≤ 1 0 5 n\leq 10^5 n105

Solution

( x , y , z , h ) (x,y,z,h) (x,y,z,h) ( A x , B y , C z , D h ) (A_x,B_y,C_z,D_h) (Ax,By,Cz,Dh)连一条边,则每个点的出度入度都为1,则整个四维空间会形成若干个环,显然答案为 n 4 n^4 n4加上环的个数。

对每个排列中的环找出来,显然不同种类不会超过 O ( n ) O(\sqrt n) O(n )个,对于每个排列中的四个环 a , b , c , d a,b,c,d a,b,c,d,他们的贡献显然是 a b c d l c m ( a , b , c , d ) \frac{abcd}{lcm(a,b,c,d)} lcm(a,b,c,d)abcd
A B AB AB的环暴力合并, C D CD CD的环也暴力合并,复杂度是 O ( n ) O(n) O(n)的,大概的形式是可以得到这样的四个数组 r , r ′ , w , w ′ r,r',w,w' r,r,w,w,现在要我们求 ∑ i ∑ j r i w j l c m ( r i ′ , w j ′ ) \sum_i\sum_j\frac{r_iw_j}{lcm(r'_i,w'_j)} ijlcm(ri,wj)riwj
我们来推推式子
∑ i ∑ j r i w j l c m ( r i ′ , w j ′ ) \sum_i\sum_j\frac{r_iw_j}{lcm(r'_i,w'_j)} ijlcm(ri,wj)riwj

∑ i ∑ j r i w j r i ′ w j ′ ∗ g c d ( r i ′ , w j ′ ) \sum_i\sum_j\frac{r_iw_j}{r'_iw'_j}*gcd(r'_i,w'_j) ijriwjriwjgcd(ri,wj)

r i = r i r i ′     w i = w i w i ′ r_i=\frac{r_i}{r'_i}\ \ \ w_i=\frac{w_i}{w'_i} ri=riri   wi=wiwi

∑ i ∑ j r i w j g c d ( r i ′ , w j ′ ) \sum_i\sum_jr_iw_jgcd(r'_i,w'_j) ijriwjgcd(ri,wj)

∑ i r i ∑ d ∣ r i ′ d ∗ ∑ j [ g c d ( w j ′ , r i ′ ) = d ] w j \sum_ir_i\sum_{d|r'_i}d*\sum_j[gcd(w'_j,r'_i)=d]w_j iridridj[gcd(wj,ri)=d]wj

∑ i r i ∑ d ∣ r i ′ d ∗ ∑ j [ g c d ( w j ′ d , r i ′ d ) = 1 ] w j \sum_ir_i\sum_{d|r'_i}d*\sum_j[gcd(\frac{w'_j}{d},\frac{r'_i}{d})=1]w_j iridridj[gcd(dwj,dri)=1]wj

∑ i r i ∑ d ∣ r i ′ d ∗ ∑ j w j ∑ k ∣ w j ′ d & & k ∣ r i ′ d μ ( k ) \sum_ir_i\sum_{d|r'_i}d*\sum_jw_j\sum_{k|\frac{w'_j}{d}\&\&k|\frac{r'_i}{d}}\mu (k) iridridjwjkdwj&&kdriμ(k)

∑ i r i ∑ d ∣ r i ′ d ∗ ∑ k ∣ r i ′ d μ ( k ) ∑ j [ k d ∣ w j ′ ] w j \sum_ir_i\sum_{d|r'_i}d*\sum_{k|\frac{r'_i}{d}}\mu (k)\sum_j[kd|w'_j]w_j iridridkdriμ(k)j[kdwj]wj

F ( v ) = ∑ j [ v ∣ w j ′ ] w j F(v)=\sum_j[v|w'_j]w_j F(v)=j[vwj]wj,则 F ( v ) F(v) F(v)可以 O ( τ ( n 2 ) n ) O(\tau(n^2)n) O(τ(n2)n)预处理出来。

∑ i r i ∑ d ∣ r i ′ d ∗ ∑ k ∣ r i ′ d μ ( k ) F ( k d ) \sum_ir_i\sum_{d|r'_i}d*\sum_{k|\frac{r'_i}{d}}\mu (k)F(kd) iridridkdriμ(k)F(kd)

t = k d t=kd t=kd,更换主体,得

∑ i r i ∑ t ∣ r i ′ F ( t ) ∗ ∑ d ∣ r i ′ d ∗ μ ( r i ′ d ) \sum_ir_i\sum_{t|r'_i}F(t)*\sum_{d|{r'_i}}d *\mu (\frac{r'_i}{d}) iritriF(t)dridμ(dri)

∑ i r i ∑ t ∣ r i ′ F ( t ) ∗ φ ( t ) \sum_ir_i\sum_{t|r'_i}F(t)*\varphi(t) iritriF(t)φ(t)

O ( τ ( n 2 ) n ) O(\tau(n^2)n) O(τ(n2)n)暴力枚举约数统计答案即可。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>

#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)

using namespace std;
typedef long long ll;
const ll N=12e4,K=N*250,P=K-11,mo=998244353;

int a[N],b[N],c[N],d[N];
int d1[N],d2[N],d3[N],d4[N];
int e1[N],e2[N],e3[N],e4[N];
int g1[N],g2[N],g3[N],g4[N];
int bz[N],y[40][2],x[40][2];
int n,gh=0;
ll ans=0;

int R[N][20],gs[N],W[N][20];
ll ke[K][2];

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

inline void add(ll x,ll del)
{
	int yu=x%P;
	while(ke[yu][0]&&ke[yu][0]!=x)yu=(yu==P-1)?0:(yu+1);
	ke[yu][0]=x;
	ke[yu][1]=(ke[yu][1]+del)%mo;
}

inline void dg1(int o,ll y,ll gx)
{
	if(o==gh+1){
		add(y,gx);
		return; 
	}
	dg1(o+1,y,gx);
	ll o1=gx*(x[o][0]-1)%mo;
	y=y*x[o][0];
	dg1(o+1,y,o1);
	fo(i,2,x[o][1]){
		o1=o1*(x[o][0])%mo;
		y=y*x[o][0];
		dg1(o+1,y,o1);
	}
}

inline ll ask(ll x)
{
	int yu=x%P;
	while(ke[yu][0]!=x&&ke[yu][0])yu=(yu==P-1)?0:(yu+1);
	return ke[yu][1];
}

inline void dg2(int o,ll y,ll gx)
{
	if(o==gh+1){
		ans=(ans+gx*ask(y))%mo;
		return; 
	}
	dg2(o+1,y,gx);
	fo(i,1,x[o][1]){
		y=y*x[o][0];
		dg2(o+1,y,gx);
	}
}

int main()
{
	scanf("%d",&n);
	fo(i,1,n)scanf("%d",&a[i]);
	fo(i,1,n)scanf("%d",&b[i]);
	fo(i,1,n)scanf("%d",&c[i]);
	fo(i,1,n)scanf("%d",&d[i]);
	fo(i,2,n){
		gs[i]=0;
		int k=i,p=(int)sqrt(i);
		fo(l,2,p)if(k%l==0){
			++gs[i];
			R[i][gs[i]]=l;
			while(k%l==0)++W[i][gs[i]],k/=l;
		}
		if(k!=1)R[i][++gs[i]]=k,W[i][gs[i]]=1;
	}
	
	fo(i,1,n)bz[i]=0;
	fo(i,1,n)if(!bz[i]){
		bz[i]=1;
		int k=1,w=i;
		while(!bz[a[w]])w=a[w],bz[w]=1,++k;
		d1[++d1[0]]=k;
	}
	sort(d1+1,d1+d1[0]+1);
	fo(i,1,d1[0])if(d1[i]!=d1[i-1]||i==1)
	e1[++e1[0]]=d1[i],g1[e1[0]]=1;
	else ++g1[e1[0]];
	
	fo(i,1,n)bz[i]=0;
	fo(i,1,n)if(!bz[i]){
		bz[i]=1;
		int k=1,w=i;
		while(!bz[b[w]])w=b[w],bz[w]=1,++k;
		d2[++d2[0]]=k;
	}
	sort(d2+1,d2+d2[0]+1);
	fo(i,1,d2[0])if(d2[i]!=d2[i-1]||i==1)
	e2[++e2[0]]=d2[i],g2[e2[0]]=1;
	else ++g2[e2[0]];
	
	fo(i,1,e1[0])fo(l,1,e2[0]){
		ll op=gcd(e1[i],e2[l]);
		ll ko=op*g1[i]%mo*g2[l]%mo;
		int j1=1,j2=1,a=e1[i],b=e2[l];
		gh=0;
		while(j1<=gs[a]||j2<=gs[b])
		if(j2>gs[b]||(R[a][j1]<R[b][j2]&&j1<=gs[a])){
			x[++gh][0]=R[a][j1];
			x[gh][1]=W[a][j1];
			++j1;
		}else
		if(j1>gs[a]||(R[b][j2]<R[a][j1]&&j2<=gs[b])){
			x[++gh][0]=R[b][j2];
			x[gh][1]=W[b][j2];
			++j2;
		}else{
			x[++gh][0]=R[a][j1];
			x[gh][1]=W[a][j1]+W[b][j2];
			++j1; ++j2;
		}
		fo(l,1,gh)while(op%x[l][0]==0)op/=x[l][0],--x[l][1];
		dg1(1,1,ko);
	}
	
	fo(i,1,n)bz[i]=0;
	fo(i,1,n)if(!bz[i]){
		bz[i]=1;
		int k=1,w=i;
		while(!bz[c[w]])w=c[w],bz[w]=1,++k;
		d3[++d3[0]]=k;
	}
	sort(d3+1,d3+d3[0]+1);
	fo(i,1,d3[0])if(d3[i]!=d3[i-1]||i==1)
	e3[++e3[0]]=d3[i],g3[e3[0]]=1;
	else ++g3[e3[0]];
	
	fo(i,1,n)bz[i]=0;
	fo(i,1,n)if(!bz[i]){
		bz[i]=1;
		int k=1,w=i;
		while(!bz[d[w]])w=d[w],bz[w]=1,++k;
		d4[++d4[0]]=k;
	}
	sort(d4+1,d4+d4[0]+1);
	fo(i,1,d4[0])if(d4[i]!=d4[i-1]||i==1)
	e4[++e4[0]]=d4[i],g4[e4[0]]=1;
	else ++g4[e4[0]];
	
	fo(i,1,e3[0])fo(l,1,e4[0]){
		ll op=gcd(e3[i],e4[l]);
		ll ko=op*g3[i]%mo*g4[l]%mo;
		int j1=1,j2=1,a=e3[i],b=e4[l];
		gh=0;
		while(j1<=gs[a]||j2<=gs[b])
		if(j2>gs[b]||(R[a][j1]<R[b][j2]&&j1<=gs[a])){
			x[++gh][0]=R[a][j1];
			x[gh][1]=W[a][j1];
			++j1;
		}else
		if(j1>gs[a]||(R[b][j2]<R[a][j1]&&j2<=gs[b])){
			x[++gh][0]=R[b][j2];
			x[gh][1]=W[b][j2];
			++j2;
		}else{
			x[++gh][0]=R[a][j1];
			x[gh][1]=W[a][j1]+W[b][j2];
			++j1; ++j2;
		}
		fo(l,1,gh)while(op%x[l][0]==0)op/=x[l][0],--x[l][1];
		dg2(1,1,ko);
	}
	ans=(ans+(ll)n*n%mo*n%mo*n)%mo;
	cout<<ans;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值