• 【BZOJ】3309: DZY Loves Math


    题意

    (T(T le 10000))次询问,每次给出(a, b(1 le a, b le 10^7)),求

    [sum_{i=1}^{a} sum_{j=1}^{b} f((i, j)) ]

    其中(f(n))表示(n)所含质因子的最大幂指数。(f(1)=0)

    分析

    以下默认(a le b)

    $$ egin{align} & sum_{i=1}^{a} sum_{j=1}^{b} f((i, j)) \ = & sum_{d=1}^{a} f(d) sum_{i=1}^{a'} sum_{j=1}^{b'} [(i, j)=1] & left( a' = left lfloor frac{a}{d} ight floor, b' = left lfloor frac{b}{d} ight floor ight) \ = & sum_{d=1}^{a} f(d) sum_{i=1}^{a'} sum_{j=1}^{b'} sum_{k|(i, j)} mu(k) \ = & sum_{d=1}^{a} f(d) sum_{k=1}^{left lfloor frac{a}{d} ight floor} mu(k) left lfloor frac{a}{kd} ight floor left lfloor frac{b}{kd} ight floor \ = & sum_{T=1}^{a} left lfloor frac{a}{T} ight floor left lfloor frac{b}{T} ight floor sum_{d|T} mu(d) f(frac{T}{d}) \ end{align} $$

    考虑(g(n) = sum_{i|n} mu(i) f(frac{n}{i}))
    (S = \{ p_i \})(p_i)(n)的质因子,则只有当(i=prod_{j in S' subseteq S} j)时才对(g(n))有贡献。
    (A subseteq S)表示指数最大(假设为(y))的质因子集合,(B=S-A)。则(i)可以看做从(A)中选出一些质因子再从(B)中选出一些质因子组合一下。
    由于(f(frac{n}{i}))的取值只取决于(i)中从(A)集合取的子集(可以发现(f)要么是(a),要么是(a-1),由(A)来决定的),所以我们只需考虑(A)的子集。
    (B eq varnothing)时,当选的(A)的子集确定后即(f(frac{n}{i}))相同时,由于从(B)中奇偶大小子集的个数相同,因此奇数个质因子的(i)和偶数个质因子的(i)的个数相同,所以(mu(i))的和为(0)。所以(g(n)=0)
    (B = varnothing)时,则只有当(i=prod_{j in S} j)(f(frac{n}{i})=y-1),否则(f(frac{n}{i})=y)。而当(f(frac{n}{i})=y)时,对于这个非全集的所有子集,奇数大小的子集和偶数大小的子集个数相差为1,计算一下就知道这种情况的贡献是((-1)^{|S|+1} a)。对于全集,贡献是((-1)^{|S|} (a-1))。所以(g(n) = (-1)^{|S|} (a-1) + (-1)^{|S|+1} a = (-1)^{|S|+1})

    于是线性筛筛出(g(n))即可。

    题解

    至于查询,分块就行了。
    复杂度(O(b+Tb^{0.5}))

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int Lim=10000005;
    int N, x[10005], y[10005], f[Lim], p[Lim], mu[Lim], cnt;
    bool np[Lim];
    ll sum[Lim];
    void init() {
    	mu[1]=1;
    	for(int i=2; i<=N; ++i) {
    		if(!np[i]) p[cnt++]=i, mu[i]=-1;
    		for(int j=0; j<cnt; ++j) {
    			int t=p[j]*i; if(t>N) break;
    			np[t]=1;
    			if(i%p[j]==0) break;
    			mu[t]=-mu[i];
    		}
    	}
    	for(int i=2; i<=N; ++i) {
    		if(mu[i]) {
    			sum[i]=-mu[i];
    		}
    	}
    	for(int i=N; i>=2; --i) {
    		if(sum[i]) {
    			for(ll j=(ll)i*i; j<=N; j*=i) {
    				sum[j]=sum[i];
    			}
    		}
    	}
    	for(int i=2; i<=N; ++i) {
    		sum[i]+=sum[i-1];
    	}
    }
    int main() {
    	int T; scanf("%d", &T);
    	for(int i=1; i<=T; ++i) scanf("%d%d", &x[i], &y[i]), N=max(N, x[i]), N=max(N, y[i]);
    	init();
    	for(int tt=1; tt<=T; ++tt) {
    		int a=x[tt], b=y[tt];
    		if(a>b) swap(a, b);
    		int now=1;
    		ll ans=0;
    		for(int i=1; i<=a; i=now+1) {
    			now=min(a/(a/i), b/(b/i));
    			ans+=(ll)(a/i)*(ll)(b/i)*(sum[now]-sum[i-1]);
    		}
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
  • 相关阅读:
    第一次上机作业
    第一次作业
    信号
    进程基础
    计算机网络(第七版)谢希仁编著 第四章课后答案详解
    shell脚本编程
    关于linux安装软件(Ubuntu)时遇见的常见问题处理
    Linux系统C语言开发环境学习
    LINUX下安装中文输入法
    处理《无法获得锁 /var/lib/dpkg/lock
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4985815.html
Copyright © 2020-2023  润新知