LOJ #2476. 「2018 集训队互测 Day 3」蒜头的奖杯(三元环计数)

    技术2024-07-20  65

    题目 泰勒应天下大雨! 类似于 S D O I 2018 SDOI2018 SDOI2018旧试题。 给 D D D, E E E, F F F卷上 μ \mu μ。 得到 D ′ , E ′ , F ′ D',E',F' D,E,F。 原式变为 ∑ i , j , k A i B j C k ∑ a ∣ i , a ∣ j D a ′ ∑ b ∣ i , b ∣ k E b ′ ∑ c ∣ j , c ∣ k F c ′ \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 i,j,kAiBjCkai,ajDabi,bkEbcj,ckFc 交换和号: ∑ a , b , c D a ′ E b ′ F c ′ ∑ lcm ⁡ ( a , b ) ∣ i , lcm ⁡ ( a , c ) ∣ j , lcm ⁡ ( b , c ) ∣ k A i , B j , C k \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,cDaEbFclcm(a,b)i,lcm(a,c)j,lcm(b,c)kAi,Bj,Ck A , B , C A,B,C A,B,C做一个变换如括号中所述( A i ′ = ∑ i ∣ d A d A'_i = \sum_{i|d} A_d Ai=idAd) 得到 A ′ , B ′ , C ′ A',B',C' A,B,C。 则原式变为 ∑ a , b , c D a ′ E b ′ F c ′ A lcm ⁡ ( a , b ) ′ B lcm ⁡ ( a , c ) ′ C lcm ⁡ ( b , c ) ′ \sum_{a,b,c} D'_aE'_bF'_cA'_{\operatorname{lcm}(a,b)}B'_{\operatorname{lcm}(a,c)}C'_{\operatorname{lcm}(b,c)} a,b,cDaEbFcAlcm(a,b)Blcm(a,c)Clcm(b,c) 所以我们就对于 lcm ⁡ a , b ≤ n \operatorname{lcm}_{a,b} \leq n lcma,bn a , b a,b a,b连边求三元环计数(注意这里是有边权有点权的三元环权值计数,权值为点权和边权六个的乘积。) 随便跑了一下最大数据发现有 m = 2625630 m=2625630 m=2625630 条边。 写一个三元环计数即可在 O ( m m ) O(m \sqrt m) O(mm )的复杂度解决此题。 虽然和标程 n n log ⁡ log ⁡ n n \sqrt n \log \log n nn loglogn比起来感觉有点不优秀( 2 e 6 2e6 2e6 m m m\sqrt m mm 也挺吓人的,本机不开 − O 2 -O2 O2跑了 10 s 10s 10s。) 但是在 L O J LOJ LOJ的实际表现是差不多的。 A C   C o d e \mathcal AC \ Code 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); }
    Processed: 0.013, SQL: 9