• 【51Nod 1363】最小公倍数之和


    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1363

    [egin{aligned} &sum_{i=1}^nfrac{in}{(i,j)}\ =&nsum_{d|n}sum_{i=1}^{frac nd}left[left(i,frac nd ight)=1 ight]i\ =&nleft(1+sum_{d|n,d eq n}sum_{i=1}^{leftlfloorfrac {n}{2d} ight floor}left[left(i,frac nd ight)=1 ight] ight)\ =&n+frac n2sum_{d|n,d eq 1}dvarphi(d) end{aligned} ]

    重点是统计(sumlimits_{d|n,d eq 1}dvarphi(d))

    [egin{aligned} &sum_{d|n,d eq 1}dvarphi(d)\ =&prodsum_{j=0}^{c_i}p_i^j imesvarphileft(p_i^j ight)-1\ =&prodleft(1+sum_{j=1}^{c_i}p_i^{2j-1}left(p_i-1 ight) ight)-1\ =&prodleft(1+frac{p_i^{2c_i+1}-p_i}{p_i+1} ight)-1 end{aligned} ]

    质因子分解统计就可以了,时间复杂度(Oleft(Tsqrt n ight))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N = 100000;
    const int p = 1000000007;
    
    bool notp[N + 3];
    int T, n, prime[N + 3], num = 0, ni[N + 3];
    
    void Euler_shai() {
    	for (int i = 2; i <= N; ++i) {
    		if (!notp[i]) prime[++num] = i;
    		for (int j = 1; j <= num && prime[j] * i <= N; ++j) {
    			notp[prime[j] * i] = true;
    			if (i % prime[j] == 0) break;
    		}
    	}
    	ni[1] = 1;
    	for (int i = 2; i <= N; ++i)
    		ni[i] = 1ll * (p - p / i) * ni[p % i] % p;
    }
    
    int ipow(int a, int b) {
    	int r = 1, w = a;
    	while (b) {
    		if (b & 1) r = 1ll * r * w % p;
    		w = 1ll * w * w % p;
    		b >>= 1;
    	}
    	return r;
    }
    
    int cal(int x) {
    	int ret = 1, ci;
    	for (int i = 1, pi = 2; i <= num && pi * pi <= x; pi = prime[++i]) {
    		if (x % pi == 0) {
    			ci = 1; x /= pi;
    			while (x % pi == 0) x /= pi, ++ci;
    			ret = 1ll * ret * (1ll * (ipow(pi, 2 * ci + 1) - pi + p) % p * ni[pi + 1] % p + 1) % p;
    		}
    	}
    	if (x > 1) {
    		ret = 1ll * ret * ((1ll * x * x % p * x % p - x + p) % p * ipow(x + 1, p - 2) % p + 1) % p;
    	}
    	return ret;
    }
    
    int main() {
    	Euler_shai();
    	
    	scanf("%d", &T);
    	while (T--) {
    		scanf("%d", &n);
    		printf("%lld
    ", (1ll * n * ni[2] % p * (cal(n) - 1) % p + n) % p);
    	}
    	return 0;
    }
    
  • 相关阅读:
    2019 SDN上机第2次作业
    2019 SDN上机第1次作业
    第07组 团队Git现场编程实战
    第二次结对编程作业
    c语言之问题集
    2019春第2次课程设计实验安排
    2019年十二周总结
    第十一周总结
    第十周作业
    第九周总结
  • 原文地址:https://www.cnblogs.com/abclzr/p/6763347.html
Copyright © 2020-2023  润新知