zoukankan      html  css  js  c++  java
  • Bzoj3309: DZY Loves Math

    题面

    传送门

    Sol

    莫比乌斯反演一波就是求

    [sum_{k=1}^{min(a,b)}lfloorfrac{a}{k} floorlfloorfrac{b}{k} floorsum_{d|k}f(d)mu(frac{k}{d}) ]

    前面的分块就好了
    考虑求

    [sum_{d|k}f(d)mu(frac{k}{d}) ]

    长的就很能筛(就是狄利克雷卷积好吗...)
    然而并不能直接筛

    考虑到(mu)函数不为(0)
    (frac{k}{d})的质因子的最大幂小于等于(1)
    假设(k)的质因子最大幂为(a)

    那么如果只要它的质因子的幂有一个不为(a),这个东西的和就是(0)
    因为无论选或者不选这个幂小于(a)的因子,对于其它的影响不变,(f=a)
    而恰恰使(mu)相反

    如果都是(a)怎么办,先假设和上面一样,贡献是(0)
    然而有一种情况使得(f=a-1),就是都选
    就要减去(1)乘以(mu)
    假设有(k)个不同的质因子,那么就是((-1)^{k+1})

    可以记录下每个数去掉最小质因数后的数,和最小质因子的幂
    然后就可以算啦

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    
    template <class Int>
    IL void Input(RG Int &x){
    	RG int z = 1; RG char c = getchar(); x = 0;
    	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	x *= z;
    }
    
    const int maxn(1e7 + 1);
    
    int prime[maxn], num, isprime[maxn], g[maxn], low[maxn], pw[maxn];
    int T, a, b;
    ll ans;
    
    IL void Sieve(){
    	isprime[1] = 1;
    	for(RG int i = 2; i < maxn; ++i){
    		if(!isprime[i]) prime[++num] = i, g[i] = pw[i] = low[i] = 1;
    		for(RG int j = 1; j <= num && prime[j] * i < maxn; ++j){
    			RG int k = i * prime[j];
    			isprime[k] = 1;
    			if(i % prime[j]){
    				low[k] = i, pw[k] = 1;
    				g[k] = pw[i] == 1 ? -g[i] : 0;
    			}
    			else{
    				low[k] = low[i], pw[k] = pw[i] + 1;
    				if(low[k] == 1) g[k] = 1;
    				else g[k] = pw[low[k]] == pw[k] ? -g[low[k]] : 0;
    				break;
    			}
    		}
    	}
    	for(RG int i = 2; i < maxn; ++i) g[i] += g[i - 1];
    }
    
    int main(RG int argc, RG char* argv[]){
    	Sieve();
    	for(Input(T); T; --T){
    		Input(a), Input(b), ans = 0;
    		if(a > b) swap(a, b);
    		for(RG int i = 1, j; i <= a; i = j + 1){
    			j = min(a / (a / i), b / (b / i));
    			ans += 1LL * (a / i) * (b / i) * (g[j] - g[i - 1]);
    		}
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Java面试中常问的Spring方面问题(涵盖七大方向共55道题,含答案)
    Node.js环境搭建
    Node.js的开源博客系统Ghost搭建教程
    探讨一个“无法创建JVM”的问题(已解决)
    Spring Boot快速入门
    Spring Boot开发Web应用
    Spring Boot工程结构推荐
    元类的剖析和单例
    多态的简单剖析、内置方法和异常的解读
    面向对象的解释和属性查找的方式解读
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8810436.html
Copyright © 2011-2022 走看看