zoukankan      html  css  js  c++  java
  • luogu3911 最小公倍数之和(莫比乌斯反演)

    link

    给定(A_1,A_2,dots,A_N),求(sum_{i=1}^Nsum_{j=1}^Nlcm(A_i,A_j))

    (1le Nle 50000;1le A_ile 50000)

    为了推式子方便我们设:

    (n=50000) (a_i=sum_{j=1}^N[A_j=i])

    答案就是(sum_{i=1}^nsum_{j=1}^na_ia_jlcm(i,j))

    (sum_{i=1}^nsum_{j=1}^na_ia_jlcm(i,j))

    (=sum_{i=1}^nsum_{j=1}^na_ia_jfrac{ij}{gcd(i,j)})

    (=sum_{p=1}^nfrac1psum_{i=1}^nsum_{j=1}^na_ia_jij[gcd(i,j)=p])

    (=sum_{p=1}^npsum_{i=1}^{n/p}sum_{j=1}^{n/p}a_{ip}a_{jp}ij[gcd(i,j)=1])

    (=sum_{p=1}^npsum_{i=1}^{n/p}sum_{j=1}^{n/p}a_{ip}a_{jp}ijsum_{d|i,d|j}mu(d))

    (=sum_{p=1}^npsum_{d=1}^nmu(d)d^2sum_{i=1}^{n/dp}sum_{j=1}^{n/dp}a_{idp}a_{jdp}ij)

    (=sum_{q=1}^nqsum_{d|q}dmu(d)sum_{i=1}^{n/q}sum_{j=1}^{n/q}a_{iq}a_{jq}ij)

    (=sum_{q=1}^nqsum_{d|q}dmu(d)left(sum_{i=1}^{n/q}a_{iq}i ight)^2)

    (sum_{i=1}^{n/q}a_{iq}i)对于每个(q)求值,总复杂度为(frac n 1+frac n 2+frac n 3+dots+frac nn)复杂度为调和级数(O(nlog n))

    前半部分筛(d)后枚举(d)及其倍数,复杂度还是调和级数(O(nlog n))

    然后直接求和就行了,貌似不用打数论分块

    41行一遍A。。。真不用打数论分块,复杂度nlogn

    #include <cstdio>
    using namespace std;
    
    int prime[50010], mu[50010], tot, fuck = 50000;
    bool vis[50010];
    long long sum1[50010], sum2[50010];
    int bucket[50010];
    
    int main()
    {
    	mu[1] = 1;
    	for (int i = 2; i <= fuck; i++)
    	{
    		if (vis[i] == false) prime[++tot] = i, mu[i] = -1;
    		for (int j = 1; j <= tot && i * prime[j] <= fuck; j++)
    		{
    			vis[i * prime[j]] = true;
    			if (i % prime[j] == 0) break;
    			mu[i * prime[j]] = -mu[i];
    		}
    		mu[i] *= i;
    	}
    	for (int d = 1; d <= fuck; d++)
    		for (int q = d; q <= fuck; q += d)
    			sum1[q] += mu[d];
    	for (int i = 1; i <= fuck; i++)
    		sum1[i] *= i;
    	int n; scanf("%d", &n);
    	for (int x, i = 1; i <= n; i++)
    		scanf("%d", &x), bucket[x]++;
    	long long ans = 0;
    	for (int q = 1; q <= fuck; q++)
    	{
    		int sb = fuck / q;
    		for (int i = 1; i <= sb; i++)
    			sum2[q] += bucket[i * q] * (long long)i;
    		ans += sum2[q] * sum1[q] * sum2[q];
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    xiaota-banzhuren-login.vue-重置密码
    xiaota-banzhuren-login.vue
    xiaota-global-index
    xiaota-router-index
    tab表格嵌套tab表格
    xiaota-selectarr
    xiaota-getlunardate
    xiaota-format
    xitaota-DataTime
    xiaota-axioslmport
  • 原文地址:https://www.cnblogs.com/oier/p/10298560.html
Copyright © 2011-2022 走看看