zoukankan      html  css  js  c++  java
  • P3312 [SDOI2014]数表 [莫比乌斯反演,树状数组]

    (sum_{i=1}^{n} sum_{j=1}^{m} sum_{d|gcd(i,j)} d)

    显然大家都会,跳过了(

    然后我们在这里加一个条件。

    (sum_{i=1}^{n} sum_{j=1}^{m} sum_{d|gcd(i,j)} d imes [sum_{d|gcd(i,j)} d leq a])

    我们暂且忽略这个玩意,定义 (sig_d = sum_{k|d} k)

    然后直接枚举这个 (d),贡献是 (sum_{d=1}^{n} sum_{i=1}^{frac{n}{d}} sum_{j=1}^{frac{m}{d}} imes sig_d [gcd(i,j)==1])

    反演常用套路,(sum_{d|n} mu_d = [n==1])

    枚举一个 (k)

    (sum_{d} sig_d sum_{k=1}^{frac{n}{d}} mu_k imes frac{n}{kd} imes frac{m}{kd})

    然后我们发现可以令 (T=kd)
    换个形式带入

    (sum_{T=1}^{n} frac{n}{T} imes frac{m}{T} sum_{d|T} sig_d imes mu_{frac{T}{d}})

    然后我们发现只有 (sig_d leq a) 的情况下才计入贡献,然后树状数组扫描线即可。

    #include <bits/stdc++.h>
    #define int long long
    #define pb push_back
    #define pii pair<int, int>
    using namespace std;
    template <class T> inline void cmax(int&x, const T&y) { (x < y) && (x = y); }
    template <class T> inline void cmin(int&x, const T&y) { (x > y) && (x = y); }
    
    const int mod = 1ll << 31;
    const int MAX = 1e5 + 1;
    struct que { int n, m, a, id; };
    
    inline void inc(int&x, int y) {
    	x += y; if(x >= mod) x -= mod;
    }
    
    signed main() {
    	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    
    	auto getmu = [&](int n) {
    		vector <int> mu(n, 0); mu[1] = 1;
    		for(int i = 1; i < n; i++)
    			for(int j = i * 2; j < n; j += i) mu[j] -= mu[i];
    		return mu;
    	};
    	
    	auto getsig = [&](int n) {
    		vector <int> sig(n, 0);
    		for(int i = 1; i < n; i++)
    			for(int j = i; j < n; j += i) inc(sig[j], i);
    		return sig;
    	};
    	
    	vector <int> mu = getmu(MAX), sig = getsig(MAX), a(MAX);
    	static int sg[(int)1e5 + 1];
    	for(int i = 0; i < MAX; i++) sg[i] = sig[i], a[i] = i;
    	sort(a.begin(), a.end(), [](int x, int y) { return sg[x] < sg[y]; });
    	int t; cin >> t;
    	vector <que> q; int cnt = 0;
    	while(t--) {
    		int n, m, a;
    		cin >> n >> m >> a;
    		if(n > m) swap(n, m);
    		q.pb({n, m, a, cnt++});
    	}
    	sort(q.begin(), q.end(), [](que x, que y) { return x.a < y.a; });
    	struct BIT {
    		vector <int> c;
    		int n;
    		BIT(const int&_n) { n = _n + 1; c.resize(n + 1); }
    		inline int low(int x) { return x & -x; }
    		inline void add(int x, int y) { inc(y, mod); for(; x < n; x += low(x)) inc(c[x], y); }
    		inline int qry(int x) { int ans = 0; for(; x; x ^= low(x)) inc(ans, c[x]); inc(ans, mod); return ans; }
    	};
    	BIT bit(MAX);
    	
    	auto ins = [&](int x) { for(int k = 1; x * k <= 1e5; k++) bit.add(x * k, mu[k] * sig[x] % mod); };
    	auto qry = [&](int n, int m) {
    		int ans = 0, las = 0, now = 0;
    		for(int l = 1, r = 0; l <= n; l = r + 1) {
    			r = min(n / (n / l), m / (m / l));
    			now = bit.qry(r);
    			inc(ans, (now - las + mod) % mod * (n / l) % mod * (m / l) % mod);
    			las = now;
    		}
    		inc(ans, mod);
    		return ans;
    	};
    	int j = 1;
    	vector <int> ans(cnt, 0);
    	for(int i = 0; i < cnt; i++) {
    		while(j < MAX && sig[a[j]] <= q[i].a) ins(a[j++]);
    		ans[q[i].id] = qry(q[i].n, q[i].m);
    	}
    	for(int i = 0; i < cnt; i++)
    		cout << ans[i] << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    自动化测试过程中所入的坑3——解决问题思维的转换
    自动化测试所入的坑2
    js原生触发angular事件
    Selenium2Library源码中browser的传递
    Selenium自动化测试中的等待
    Android adb 命令学习笔记
    Robot学习笔记
    Xpath 与Css 定位方式的比较
    Selenium填坑笔记
    python批量更改文件名
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12964882.html
Copyright © 2011-2022 走看看