• loj#2565. 「SDOI2018」旧试题(反演 三元环计数)


    题意

    题目链接

    Sol

    神仙反演题。在洛谷上疯狂被卡常

    Orz shadowice

    #include<bits/stdc++.h>
    #define Pair pair<int, int>
    #define MP make_pair
    #define fi first
    #define se second 
    #define LL long long 
    
    const int MAXN = 2e5 + 10, mod = 1e9 + 7;
    using namespace std;
    template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;}
    template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;}
    template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;}
    template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);}
    template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;}
    template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;}
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * f;
    }
    int mu[MAXN], prime[MAXN], vis[MAXN], tot, A, B, C, num, deg[MAXN];
    int fa[MAXN], fb[MAXN], fc[MAXN];
    vector<LL> di[MAXN];
    vector<Pair> v[MAXN];//每个数的质因数分解 
    struct Edge {
    	LL u, v, w;
    }E[MAXN * 10];
    void GetPrime(int N) {
    	vis[1] = 1; mu[1] = 1;
    	for(int i = 2; i <= N; i++) {
    		if(!vis[i]) prime[++tot] = i, mu[i] = -1;
    		for(int j = 1; j <= tot && i * prime[j] <= N; j++) {
    			vis[i * prime[j]] = 1;
    			if(i % prime[j]) mu[i * prime[j]] = -mu[i];
    			else {mu[i * prime[j]] = 0; break;}
    		}
    	}
    	for(int i = 1; i <= tot; i++) 
    		for(int j = 1; j * prime[i] <= N; j++) 
    			di[j * prime[i]].push_back(prime[i]);
    		
    }
    
    void Get(int *a, int N, int X) {
    	for(int i = 1; i <= N; i++)
    		for(int j = i; j <= N; j += i) a[i] += X / j;
    }
    LL lcm(int a, int b) {
    	return 1ll * a / __gcd(a, b) * b;
    }
    void init() {
    	memset(fa, 0, sizeof(fa));
    	memset(fb, 0, sizeof(fb));
    	memset(fc, 0, sizeof(fc));
    	memset(deg, 0, sizeof(deg));
    	num = 0;
    	for(int i = 1; i <= A; i++) v[i].clear();
    }
    void Build() {
    	for(int w = 1; w <= A; w++) {//lcm(u, v) = w;
    		if(!mu[w]) continue;
    		int n = di[w].size();
    		//for(auto x : di[w]) printf("%d ", x); puts("");
    		for(int sta = 0; sta < (1 << n); sta++) {
    			LL i = 1;
    			for(int b = 0; b < n; b++) 
    				if(sta >> b & 1) i *= di[w][b];
    			for(int s = sta; ; s = sta & (s - 1)) {//tag
    				LL g = 1;
    				for(int b = 0; b < n; b++) 
    					if(s >> b & 1) 
    						g *= di[w][b];
    				int j = w * g / i; 
    				if(i < j) E[++num] = {i, j, w};// printf("%d
    ", num);
    				if(!s) break;
    			}
    		}
    	}
    }
    
    LL fuck(int x, int y, int w) {
    	if(mu[x] == 1) 
    		return add(add(mul(mul(fa[w], fb[w]), fc[y]), mul(mul(fa[w], fb[y]), fc[w])), mul(mul(fa[y], fb[w]), fc[w]));
    	else 
    		return (-add(add(mul(mul(fa[w], fb[w]), fc[y]), mul(mul(fa[w], fb[y]), fc[w])), mul(mul(fa[y], fb[w]), fc[w])) + mod) % mod;
    }
    
    LL calc() {
    //	for(int i = 1; i <= A; i++) for(auto &x : v[i])printf("%d %d %d
    ", i, x.fi, x.se);
    	for(int i = 1; i <= num; i++) {
    		int x = E[i].u, y = E[i].v;
    		if(deg[x] > deg[y]) swap(x, y);
    		v[y].push_back(MP(x, E[i].w));
    	}
    	LL ans = 0;
    	for(int a = 1; a <= A; a++) {
    		for(auto &t1 : v[a]) {
    			LL b = t1.fi, w1 = t1.se;
    			for(auto &t2 : v[b]) {
    				LL c = t2.fi, w2 = t2.se, xi = mu[a] * mu[b] * mu[c];
    				LL w3 = lcm(a, c);
    				if(w3 > A) continue;
    				if(xi == 1) {
    					add2(ans, mul(mul(fa[w1], fb[w2]), fc[w3]));
    					add2(ans, mul(mul(fa[w1], fb[w3]), fc[w2]));
    					add2(ans, mul(mul(fa[w2], fb[w1]), fc[w3]));
    					add2(ans, mul(mul(fa[w2], fb[w3]), fc[w1]));
    					add2(ans, mul(mul(fa[w3], fb[w1]), fc[w2]));
    					add2(ans, mul(mul(fa[w3], fb[w2]), fc[w1]));
    				} else if(xi == -1) {
    					add2(ans, mul(mul(-fa[w1], fb[w2]), fc[w3]));
    					add2(ans, mul(mul(-fa[w1], fb[w3]), fc[w2]));
    					add2(ans, mul(mul(-fa[w2], fb[w1]), fc[w3]));
    					add2(ans, mul(mul(-fa[w2], fb[w3]), fc[w1]));
    					add2(ans, mul(mul(-fa[w3], fb[w1]), fc[w2]));
    					add2(ans, mul(mul(-fa[w3], fb[w2]), fc[w1]));					
    				}
    			//	cout << ans << endl;
    			}
    		}
    	}
    
    	for(int i = 1; i <= num; i++) {//有两个一样 
    		add2(ans, fuck(E[i].u, E[i].v, E[i].w));
    		add2(ans, fuck(E[i].v, E[i].u, E[i].w));
    	}
    	for(int i = 1; i <= C; i++) {//全都一样 
    		if(mu[i] == 1) add2(ans, mul(mul(fa[i], fb[i]), fc[i]));
    		else if(mu[i] == -1) add2(ans, -mul(mul(fa[i], fb[i]), fc[i]) + mod);
    	}
    		
    	return ans;
    }
    void solve() {
    	init();
    	A = read(); B = read(); C = read();
    	if(A < B) swap(A, B); if(C > B) swap(B, C); if(A < B) swap(A, B); 
    	Get(fa, A, A); Get(fb, A, B); Get(fc, A, C);	
    	Build();
    	cout << calc() << '
    ';
    }
    signed main() {
    //	freopen("gg1.txt", "w", stdout);
    	
    	GetPrime(2e5);
    	for(int T = read(); T; T--, solve());
    	return 0;
    }
    
  • 相关阅读:
    sscanf 函数
    hdu 1232 畅通工程 解题报告
    hdu 2048 神、上帝以及老天爷 解题报告
    hdu 2049 不容易系列之(4)——考新郎 解题报告
    hdu 2013 蟠桃记 解题报告
    hdu 2093 考试排名 解题报告
    分糖果 的解题报告
    hdu 2017 字符串统计 解题报告
    表的连接方式:NESTED LOOP、HASH JOIN、SORT MERGE JOIN【转】
    sort_area_size设置【转】
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/10363241.html
Copyright © 2020-2023  润新知