• 【JZOJ4782】【NOIP2016提高A组模拟9.15】Math


    题目描述

    这里写图片描述

    输入

    这里写图片描述

    输出

    这里写图片描述

    样例输入

    3 5

    样例输出

    -1

    数据范围

    这里写图片描述

    解法

    观察式子,可以得知整个式子与d(i*j)的奇偶性有关。
    d(n)为奇数当且仅当n是完全平方数。
    对于一个i,如果d(i*j) (j∈[1,m])有奇数个完全平方数,那么d的和即为奇数,则贡献为-1;否则为1。
    那么我们考虑如何求d(i*j)有多少个奇数,也即有多少个完全平方数。


    我们设i=kq2(q极大,q,k均为整数);
    如果我们要使i*j是完全平方数,那么j必须满足j=kp2(p极大,p,k均为整数);
    因为j必须要使i中的因子k也变为平方因子,j中就必须有k这个因子。
    然后,i*j的完全平方数就有mk个。
    那么问题就在于如何快速求出对于每个i的k。


    设k(i)是对于i的所谓的k;
    考虑线性筛法;
    设j是i的一个质因数。
    如果i|k(j/i),那么k(i)=k(j/i)/i;否则k(i)=k(j/i)*i。
    边界是k(1)=1,k(p)=p(p为素数)。
    那么就可以用线性筛法O(n)完成对k的求解了。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    #define ll long long
    #define ln(x,y) int(log(x)/log(y))
    #define sqr(x) ((x)*(x))
    using namespace std;
    const char* fin="aP1.in";
    const char* fout="aP1.out";
    const int inf=0x7fffffff;
    const int maxn=10000007;
    ll n,m,i,j,k,ans,tmp,tmd;
    ll yue[maxn],b[maxn];
    bool bz[maxn];
    int main(){
        scanf("%lld%lld",&n,&m);
        b[1]=1;
        for (i=2;i<=n;i++){
            if (!bz[i]){
                yue[++yue[0]]=i;
                b[i]=i;
            }
            for (j=1;j<=yue[0];j++){
                if (yue[j]*i>n) break;
                bz[yue[j]*i]=true;
                if (b[i]%yue[j]==0) b[yue[j]*i]=b[i]/yue[j];
                else b[yue[j]*i]=b[i]*yue[j];
                if (i%yue[j]==0) break;
            }
        }
        for (i=1;i<=n;i++){
            if ((ll)sqrt(m/b[i])%2==0) ans++;
            else ans--;
        }
        printf("%lld",ans);
        return 0;
    }

    启发

    1.非常重要的是在于问题的转化;
    2.考虑完全平方数的时候,要把i拆成kp2的形式。
    3.线筛的运用。

    线筛的性质

    每个数i都会由它的最小质因数来筛除。
    也即i=p*j(p是i的最小质因数)。

    性质

    每个数被筛且只被筛一次,也就是所谓O(n)复杂度的原因。

    证明

    假设这个数i由x1,x2两个质因数来筛除,且x1<x2
    也即i=x1j,i=x2k;
    那么x1必须不能整除k,否则当循环x1*k的时候会break。
    所以无论k和x2里面都没有x1这个质因数,k*x2也不会有x1这个质因数。
    与假设矛盾。
    所以i被筛且只被筛一次。

    应用

    1.求素数。
    2.如果函数f(x)可以由f(x/p) (p是质数)O(1)转移,那么f(x)能够用线筛O(n)求解。大概积性函数的线筛求解也是这个道理。

  • 相关阅读:
    轻松搭建Redis缓存高可用集群
    Redis集群主从配置
    启动Redis Cluster
    MyISAM 和 InnoDB 索引的区别
    数据库面试
    如何定位php程序访问慢
    Socket技术详解
    NGINX快速入门
    nginx 并发数问题思考:worker_connections,worker_processes与 max clients
    php-fpm运行原理
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714897.html
Copyright © 2020-2023  润新知