• P1829 [国家集训队]Crash的数字表格 / JZPTAB [莫比乌斯反演,狄利克雷前缀和]


    (sum_{i=1}^{n}sum_{j=1}^{m} lcm(i,j) = frac{i,j}{gcd(i,j)})

    枚举 (gcd)

    (sum_{d=1}^{n}sum_{i=1}^{n/d}sum_{j=1}^{m/d}ij imes d[gcd(i,j)==1])

    (sum_{i|n} mu(i) = [n==1])

    所以

    (sum_{d=1}^{n}sum_{i=1}^{n/d}sum_{j=1}^{m/d}ij imes d sum_{k|gcd(i,j)} mu(k))

    枚举 (k)!
    因为 (k|gcd(i,j)),所以 (k|i,k|j)

    (sum_{d=1}^{n}sum_{k=1}^{n}mu(k)sum_{i=1}^{n/kd}sum_{j=1}^{m/kd}ikjk imes d)

    发现 (sum_{i=1}^{x}sum_{j=1}^{y}ij = sum2(x) imes sum2(y))
    此处定义 (sum2(x) = frac{(1+x) imes x}{2})

    然后原式就相当于

    (sum_{d=1}^{n}dsum_{k=1}^{n}k^2mu(k)sum2(n/kd) imes sum2(m/kd))

    发现 (d imes k leq n)
    枚举 (d imes k)

    然后狄利克雷前缀和一下就没了。

    // by Isaunoya
    #pragma GCC optimize(3)
    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    const int mod = 20101009;
    
    signed main() {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr), cout.tie(nullptr);
    
    	auto add = [&](int&a, const int&b) {
    		a += b;
    		if(a >= mod)
    			a -= mod;
    	};
    	
    	auto init = [&](int n) {
    		vector <int> mu(n + 1, 0);
    		for(int i = mu[1] = 1; i <= n; i++)
    			for(int j = i * 2; j <= n; j += i)
    				mu[j] -= mu[i];
    		
    		vector <bool> vis(n + 1, 0);
    		vector <int> prime;
    		for(int i = 2; i <= n; i++) {
    			if(vis[i])
    				continue;
    			prime.pb(i);
    			for(int j = i * 2; j <= n; j += i)
    				vis[j] = 1;
    		}
    		
    		vector <int> sum(n + 1, 0);
    		for(int i = 1; i <= n; i++) 
    			sum[i] = (mu[i] * i + mod) % mod;
    		for(int p: prime)
    			for(int j = 1; j * p <= n; j++)
    				add(sum[p * j], sum[j]);
    		return sum;
    	};
    	
    	int n, m;
    	cin >> n >> m;
    	if(n > m)
    		swap(n, m);
    	vector <int> s = init(n);
    	
    	auto get = [&](const int&x) {
    		int res = 1ll * x * s[x] % mod;
    		auto sum = [&](const int&x) { return 1ll * x * (x + 1) / 2 % mod; };
    		res = 1ll * res * sum(n / x) % mod;
    		res = 1ll * res * sum(m / x) % mod;
    		return res;
    	};
    	
    	int ans = 0;
    	for(int i = 1; i <= n; i ++)
    		add(ans, get(i));
    	cout << ans << '
    ';	
    	return 0;
    }
    
  • 相关阅读:
    Linux线程同步方法
    Linux进程间通信:信号
    孤儿进程僵尸进程及其回收
    Linux守护进程
    Linux系统编程常见函数 (进程/线程)
    Linux系统编程常用函数 (文件/目录)
    C++实现贪吃蛇小游戏
    C++实现简易Vector类
    C++实现简易版字符串类
    《图解HTTP》读书笔记
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12900107.html
Copyright © 2020-2023  润新知