LOJ #2476. 「2018 集訓隊互測 Day 3」蒜頭的獎盃(三元環計數)

題目
泰勒應天下大雨!
類似於SDOI2018SDOI2018舊試題。
DD,EE,FF捲上μ\mu
得到D,E,FD',E',F'
原式變爲i,j,kAiBjCkai,ajDabi,bkEbcj,ckFc\sum_{i,j,k} A_iB_jC_k \sum_{a|i,a|j} D'_a \sum_{b|i,b|k} E'_b \sum_{c|j,c|k} F'_c
交換和號:
a,b,cDaEbFclcm(a,b)i,lcm(a,c)j,lcm(b,c)kAi,Bj,Ck\sum_{a,b,c} D'_aE'_bF'_c\sum_{\operatorname{lcm}(a,b)|i,\operatorname{lcm}(a,c)|j,\operatorname{lcm}(b,c)|k} A_i,B_j,C_k
A,B,CA,B,C做一個變換如括號中所述(Ai=idAdA'_i = \sum_{i|d} A_d
得到A,B,CA',B',C'
則原式變爲a,b,cDaEbFcAlcm(a,b)Blcm(a,c)Clcm(b,c)\sum_{a,b,c} D'_aE'_bF'_cA'_{\operatorname{lcm}(a,b)}B'_{\operatorname{lcm}(a,c)}C'_{\operatorname{lcm}(b,c)}
所以我們就對於lcma,bn\operatorname{lcm}_{a,b} \leq na,ba,b連邊求三元環計數(注意這裏是有邊權有點權的三元環權值計數,權值爲點權和邊權六個的乘積。)
隨便跑了一下最大數據發現有m=2625630m=2625630 條邊。
寫一個三元環計數即可在O(mm)O(m \sqrt m)的複雜度解決此題。
雖然和標程nnloglognn \sqrt n \log \log n比起來感覺有點不優秀(2e62e6mmm\sqrt m也挺嚇人的,本機不開O2-O2跑了10s10s。)
但是在LOJLOJ的實際表現是差不多的。
AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 100005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long 
#define pii pair<int,LL>
#define mp make_pair
#define vi vector<pair<int,LL> >
#define pb emplace_back
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
template<class T>void read(T &res){
	char ch;
	for(;!isdigit(ch=getc()););
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}


int n,mu[maxn],pr[maxn],cnt_pr,vis[maxn],in[maxn];
LL A[6][maxn],B[6][maxn],ans;
int gcd(int a,int b){ return !b ? a : gcd(b,a%b); } 
void upd(int a,int b,int c,int lab,int lbc,int lac){
	ans += 
	B[0][lab] * B[1][lac] * B[2][lbc] * B[3][a] * B[4][b] * B[5][c] + 
	(a != b ? B[0][lab] * B[1][lbc] * B[2][lac] * B[3][b] * B[4][a] * B[5][c] : 0) + 
	(b != c ? B[0][lac] * B[1][lab] * B[2][lbc] * B[3][a] * B[4][c] * B[5][b] : 0) + 
	(a != c ? B[0][lbc] * B[1][lac] * B[2][lab] * B[3][c] * B[4][b] * B[5][a] : 0) + 
	(a != b && b != c && a != c ? 
		B[0][lbc] * B[1][lab] * B[2][lac] * B[3][b] * B[4][c] * B[5][a] + 
		B[0][lac] * B[1][lbc] * B[2][lab] * B[3][c] * B[4][a] * B[5][b] : 0);
}
vi G[maxn],E[maxn];
int tim;
LL cst[maxn];

int main(){
	read(n);
	rep(t,0,5) rep(i,1,n) read(A[t][i]);
	rep(t,0,2) rep(i,1,n) for(int k=i;k<=n;k+=i) B[t][i] += A[t][k];
	mu[1] = 1;
	rep(i,2,n){
		if(!vis[i]) pr[cnt_pr++] = i , mu[i] = -1;
		for(int j=0;pr[j] * i <= n;j++){
			vis[i * pr[j]] = 1;
			if(i % pr[j]) mu[i * pr[j]] = -mu[i];
			else{
				mu[i * pr[j]] = 0;
				break;
			}
		}
	}
	memset(vis,0,sizeof vis);
	rep(t,3,5) rep(i,1,n) for(int k=i,p=1;k<=n;k+=i,p++) B[t][k] += A[t][i] * mu[p];
	rep(i,1,n) upd(i,i,i,i,i,i);
	rep(i,1,n){
		static int ar[maxn]={},cnt,t;
		cnt = 0;
		for(int j=i;j<=n;j+=i) ar[++cnt] = j;
		rep(j,1,cnt) for(int k=1;k<j && (t = ar[j] / i * ar[k]) <= n;k++) if(gcd(ar[j] , ar[k]) == i){
			int x = ar[j] , y = ar[k];
			upd(x,x,y,x,t,t);
			upd(y,y,x,y,t,t);
			in[x] ++ , in[y] ++;
			G[x].pb(mp(y,t));
		}
	}
	rep(i,1,n) for(auto v:G[i])
		if(in[i] < in[v.first]) E[i].pb(v);
		else E[v.first].pb(mp(i,v.second));
	rep(i,1,n){
		++tim;
		for(auto v:E[i]) vis[v.first] = tim , cst[v.first] = v.second;
		for(auto v:E[i]) for(auto p:E[v.first])
			if(vis[p.first] == tim)
				upd(i,v.first,p.first,v.second,p.second,cst[p.first]);
	}
	printf("%llu",(unsigned long long)ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章