zoukankan      html  css  js  c++  java
  • [SDOI2018] 旧试题

    推狮子的部分

    [sum_{i=1}^Asum_{j=1}^Bsum_{k=1}^Csigma(ijk) =sum_{i=1}^Asum_{j=1}^Bsum_{k=1}^Csum_{x|i}sum_{y|j}sum_{z|k}epsilon(gcd(x,y))epsilon(gcd(y,z))epsilon(gcd(x,z))\ =sum_{i=1}^Asum_{x|i}sum_{j=1}^Bsum_{y|j}sum_{k=1}^Csum_{z|k}epsilon(gcd(x,y))epsilon(gcd(y,z))epsilon(gcd(x,z))\ =sum_{x=1}^Alfloorfrac{A}{x} floorsum_{y=1}^Blfloorfrac{B}{y} floorsum_{z=1}^Clfloorfrac{C}{z} floorepsilon(gcd(x,y))epsilon(gcd(y,z))epsilon(gcd(x,z))\ =sum_{x=1}^Alfloorfrac{A}{x} floorsum_{y=1}^Blfloorfrac{B}{y} floorsum_{z=1}^Clfloorfrac{C}{z} floorsum_{d|x,d|y}mu(d)sum_{p|y,p|z}mu(p)sum_{q|x,q|z}mu(q)\ =sum_{d=1}^{min(A,B)}mu(d)sum_{p=1}^{min(B,C)}mu(p)sum_{q=1}^{min(A,C)}mu(q)sum_{d|x,q|x}^Alfloorfrac{A}{x} floorsum_{d|y,p|y}^Blfloorfrac{B}{y} floorsum_{p|z,q|z}^Clfloorfrac{C}{z} floor\ =sum_{d=1}^{min(A,B)}mu(d)sum_{p=1}^{min(B,C)}mu(p)sum_{q=1}^{min(A,C)}mu(q)sum_{lcm(d,q)|x}^Alfloorfrac{A}{x} floorsum_{lcm(d,p)|y}^Blfloorfrac{B}{y} floorsum_{lcm(p,q)|z}^Clfloorfrac{C}{z} floor\ ext{define } f(n,t)=sum_{t|x}lfloorfrac{n}{x} floor ,N=max(A,B,C)\ cdots=sum_{d=1}^Nmu(d)sum_{p=1}^Nmu(p)sum_{q=1}^Nmu(q)f(A,lcm(d,q))f(B,lcm(d,p))f(C,lcm(p,q))\ ]

    计算答案

    其中(f(n,t))可以(O(nlog n))预处理。

    考虑对(T)个点连边建图,(u)(v)之间有边当且仅当(mu(u) ot=0,mu(v) ot=0,lcm(a,b) ot>T)。那么图中的每个三元环都能算入答案,这里的三元环还包括只有俩点的和只有单点的。

    对于包含三个点的(<d,p,q>)的贡献为

    [mu(d)mu(p)mu(q) imes\ (f(A,lcm(d,q))f(B,lcm(d,p))f(C,lcm(p,q))+\ f(A,lcm(d,q))f(B,lcm(p,q))f(C,lcm(d,p))+\ f(A,lcm(d,p))f(B,lcm(d,q))f(C,lcm(p,q))+\ f(A,lcm(d,p))f(B,lcm(p,q))f(C,lcm(d,q))+\ f(A,lcm(p,q))f(B,lcm(d,p))f(C,lcm(d,q))+\ f(A,lcm(p,q))f(B,lcm(d,q))f(C,lcm(d,p))) ]

    对于包含两个、一个的环同理。统计三元环的方法参照不常用的黑科技——「三元环」

    参考实现

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    const int mod=1e9+7;
    
    //[SDOI2018]旧试题
    
    int pr[N],cnt;
    int mu[N],bk[N],deg[N];
    long long fa[N],fb[N],fc[N]; 
    bool vis[N];
    struct Node {int u,v,w;};
    struct Edge {int ver,len;};
    
    Node ech[N*300];
    vector<Edge> e[N];
    
    int solve(int a,int b,int c) {
    	long long ans=0;
    	int n=max(a,max(b,c)),m=0;
    	for(int i=1; i<=n; ++i) {
    		deg[i]=fa[i]=fb[i]=fc[i]=0;
    		e[i].clear();
    	}
    	for(int i=1; i<=n; ++i) {
    		for(int x=i; x<=n; x+=i) {
    			fa[i]+=a/x,fb[i]+=b/x,fc[i]+=c/x;
    		}
    	}
    	for(int i=1; i<=a&&i<=b&&i<=c; ++i) {
    		if(mu[i]) ans+=mu[i]*mu[i]*mu[i]*fa[i]*fb[i]*fc[i];
    	}
    	for(int g=1; g<=n; ++g) {
    		for(int i=1; i*g<=n; ++i) if(mu[i*g]) {
    			for(int j=i+1; 1LL*i*j*g<=n; ++j) if(mu[j*g]&&__gcd(i,j)==1) {
    				int u=i*g,v=j*g,w=i*j*g; 
    				deg[u]++,deg[v]++,ech[++m]=(Node){u,v,w};
    				ans+=mu[u]*mu[u]*mu[v]*(fa[u]*fb[w]*fc[w]+fa[w]*fb[u]*fc[w]+fa[w]*fb[w]*fc[u]);
    				ans+=mu[u]*mu[v]*mu[v]*(fa[v]*fb[w]*fc[w]+fa[w]*fb[v]*fc[w]+fa[w]*fb[w]*fc[v]);
    			}
    		}
    	}
    	for(int i=1; i<=m; ++i) {
    		if(deg[ech[i].u]<deg[ech[i].v]||(deg[ech[i].u]==deg[ech[i].v]&&ech[i].u<ech[i].v)) 
    			swap(ech[i].u,ech[i].v);
    		e[ech[i].u].push_back((Edge){ech[i].v,ech[i].w});
    	}
    #define veit vector<Edge>::iterator 
    	for(int i=1; i<=n; ++i) if(mu[i]) {
    		for(veit j=e[i].begin(); j!=e[i].end(); ++j) bk[j->ver]=j->len;
    		for(veit j=e[i].begin(); j!=e[i].end(); ++j) {
    			for(veit k=e[j->ver].begin(); k!=e[j->ver].end(); ++k) {
    				if(!bk[k->ver]) continue;
    				ans+=mu[i]*mu[j->ver]*mu[k->ver]*(
    					fa[j->len]*fb[k->len]*fc[bk[k->ver]]+fa[j->len]*fb[bk[k->ver]]*fc[k->len]+fa[k->len]*fb[j->len]*fc[bk[k->ver]]+
    					fa[k->len]*fb[bk[k->ver]]*fc[j->len]+fa[bk[k->ver]]*fb[j->len]*fc[k->len]+fa[bk[k->ver]]*fb[k->len]*fc[j->len]
    				);
    			}
    		}
    		for(veit j=e[i].begin(); j!=e[i].end(); ++j) bk[j->ver]=0;
    	}
    	return (ans%mod+mod)%mod;
    }
    
    void sieve() {
    	mu[1]=1;
    	for(int i=2; i<N; ++i) {
    		if(!vis[i]) mu[pr[++cnt]=i]=-1;
    		for(int j=1; j<=cnt&&i*pr[j]<N; ++j) {
    			vis[i*pr[j]]=1;
    			if(i%pr[j]==0) break;
    			else mu[i*pr[j]]=-mu[i];
    		}
    	}
    }
    
    int main() {
    	sieve();
    	int T,a,b,c;
    	scanf("%d",&T);
    	while(T--) {
    		scanf("%d%d%d",&a,&b,&c);
    		printf("%d
    ",solve(a,b,c)); 
    	}
    	return 0;
    }
    
  • 相关阅读:
    最漂亮( iTerm2+oh-my-zsh配色)
    python对excel的操作
    appium环境搭建
    Python单元测试unittest
    git命令日常总结
    mongon数据库的查询样例
    组合逻辑电路笔记
    Jlink驱动下载
    机组笔记
    计算机网络随笔(一部分知识点)
  • 原文地址:https://www.cnblogs.com/nosta/p/10544559.html
Copyright © 2011-2022 走看看