zoukankan      html  css  js  c++  java
  • D、brz的函数(牛客练习赛72)

    D、brz的函数

    ( sum_{i=1}^nsum_{j=1}^nmu(ij)=sum_{i=1}^nsum_{j=1}^nmu(i)mu(j)[gcd(i,j)=1]=sum_{i=1}^nsum_{j=1}^nmu(i)mu(j)sum_{d|gcd(i,j)}mu(d)=sum_{i=1}^nsum_{j=1}^nmu(i)mu(j)sum_{d|i,j}mu(d)=sum_{d=1}^nmu(d)sum_{d|i}mu(i)sum_{d|j}mu(j)=sum_{d=1}^nmu(d)left(sum_{d|i}mu(i) ight)^2 )
    将公式化简如上,发现该式子只需要求出两部分(mu)函数以及(sum_{d|i}mu(i))(某个因子(d)倍数的(mu)函数和),发现无法在T循环内求出,只能预先处理,定义两个新变量数组mu_fac_sum和ans.mu_fac_sum[i]表示因子i倍数的(mu)之和;ans[i]表示n==i时原式答案,我们预先处理每一个n,发现n-1的值会对n的值有所贡献,以及n的因子中增值的贡献,时间复杂度(O(nlogn+n^{frac{3}{2}}))

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int NMAX = 5e4 + 2;
    typedef long long ll;
    ll mu[NMAX],mu_fac_sum[NMAX],ans[NMAX];
    int prime[NMAX],isw[NMAX],tot;
    
    void init()
    {
        mu[1] = 1;
        for(int i = 2; i < NMAX; i++)
        {
            if( !isw[i] )
            {
                prime[tot++] = i;
                mu[i] = -1;
            }
            for(int j = 0; j < tot; j++)
            {
                if(i * prime[j] >= NMAX) break;
                isw[i * prime[j]] = true;
                if( i % prime[j] == 0)
                {
                    mu[i * prime[j]] = 0;
                    break;
                }
                else
                {
                    mu[i * prime[j]] = -mu[i];
                }
            }
        }
        ans[1] = 1;
        mu_fac_sum[1] = 1;
        for(int i = 2;i < NMAX;i++)
        {
            ans[i] = ans[i - 1];
            for(int j = 1;j * j <= i;j++)
            {
                if(i % j == 0)
                {
                    ans[i] += mu[j]*(mu[i]*mu[i]+2*mu[i]*mu_fac_sum[j]);
                    mu_fac_sum[j] += mu[i];
                    if(j * j != i)
                    {
                        ans[i] += mu[i/j]*(mu[i]*mu[i]+2*mu[i]*mu_fac_sum[i/j]);
                        mu_fac_sum[i/j] += mu[i];
                    }
                }
            }
        }
    }
    
    int main()
    {
        int t, n;
        init();
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            printf("%lld
    ",ans[n]);
        }
        return 0;
    }
    
  • 相关阅读:
    node.js入门
    分布式爬虫
    ES6入门
    Vue.js入门
    用scrapy爬取亚马逊网站项目
    垃圾回收器
    HTTP协议详解
    有效的邮箱地址
    C#中正则表达式的使用
    抽象类
  • 原文地址:https://www.cnblogs.com/lemon-jade/p/13939139.html
Copyright © 2011-2022 走看看