zoukankan      html  css  js  c++  java
  • 51Nod 欢乐手速场1 C 开心的小Q[莫比乌斯函数]

    tangjz (命题人)
    quailty (测试)
     
    基准时间限制:1 秒 空间限制:131072 KB 分值: 80
    如果一个数字存在一个约数是完全平方数,那么小Q就认为这个数是有趣的。
    小Q喜欢收集有趣的数字,每找到一个有趣的数,小Q就会变得很开心。
    小Q发现12是有趣的,18也是有趣的,它们都是36的约数,而在36的约数中,还有3个数是有趣的,它们是4、9、36。
    小Q很好奇,在a~b里每个数字各有多少个有趣的约数,由于a和b太大了,所以他只想知道这些个数之和是多少。
    例如4有1个有趣的约数,8有2个有趣的约数,9有1个有趣的约数,所以1~10里每个数的有趣约数个数之和是4。
    Input
    输入数据包括2个数:a, b,中间用空格分隔。(1≤a≤b≤10^9)
    Output
    输出a~b里每个数字的有趣约数个数之和。
    Input示例
    1 10
    Output示例
    4


    标解:http://www.51nod.com/contest/problemSolution.html#!problemId=1742


    里面的式子改写一开始一直不明白,稍微有点明白了,说说另一种想的方法吧
    最暴力的是枚举数字再枚举约数看看是不是平方因子数了
    一个简单的优化是枚举约数i,约数i的贡献(倍数的数量)就是[n/i]
    但还是会T
    一个巧妙的想法是我们枚举是几倍,当前枚举的是i倍,那么满足i倍<=n的数字就是<=[n/i],答案加上<=[n/i]的平方因子数的个数,就是标解中最后的式子了
    计算的时候用了两次分块n/(i*i)和n/i做到O(n^2/3)
    然而比只一次分块还慢是什么鬼?sqrt的问题吗
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline int read(){
        char c=getchar();ll x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int a,b;
    bool notp[N];
    int p[N],mu[N];
    void sieve(int n){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!notp[i]) p[++p[0]]=i,mu[i]=-1;
            for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
                notp[i*p[j]]=1;
                if(i%p[j]==0) break;
                mu[i*p[j]]=-mu[i];
            }
        }
        //for(int i=1;i<=n;i++) printf("mu %d %d
    ",i,mu[i]);
        //for(int i=1;i<=n;i++) mu[i]+=mu[i-1];
    }
    //int F(int n){
    //    int _=0,r=0,m=sqrt(n);
    //    for(int i=1;i<=m;i=r+1){
    //        r=n/(n/(i*i));
    //        _+=n/(i*i)*(mu[r]-mu[i-1]);
    //    }
    //    return n-_;
    //}
    int f(int n){
        int _=0,m=sqrt(n);
        for(int i=1;i<=m;i++)
            _+=n/(i*i)*mu[i];
        return n-_;
    }
    ll S(int n){//printf("n %d
    ",n);
        ll ans=0;int r=0;
        for(int i=1;i<=n;i=r+1){
            r=n/(n/i);
            ans+=(r-i+1)*f(n/i);
            //printf("f %d  %d %d  %d
    ",n/i,i,r,f(n/i));
        }
        return ans;
    }
    int main(){
        //freopen("in","r",stdin);
        a=read();b=read();
        sieve(sqrt(b)+1);
        printf("%lld",S(b)-S(a-1));
    }
    一次分块
    
    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline int read(){
        char c=getchar();ll x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int a,b;
    bool notp[N];
    int p[N],mu[N];
    void sieve(int n){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!notp[i]) p[++p[0]]=i,mu[i]=-1;
            for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
                notp[i*p[j]]=1;
                if(i%p[j]==0) break;
                mu[i*p[j]]=-mu[i];
            }
        }
        //for(int i=1;i<=n;i++) printf("mu %d %d
    ",i,mu[i]);
        for(int i=1;i<=n;i++) mu[i]+=mu[i-1];
    }
    int F(int n){//printf("F %d
    ",n);
        int _=0,r=0,m=sqrt(n);
        for(int i=1;i<=m;i=r+1){
            r=sqrt(n/(n/(i*i)));//printf("r %d
    ",r);
            _+=n/(i*i)*(mu[r]-mu[i-1]);
        }
        return n-_;
    }
    ll S(int n){//printf("n %d
    ",n);
        ll ans=0;int r=0;
        for(int i=1;i<=n;i=r+1){
            r=n/(n/i);
            ans+=(r-i+1)*F(n/i);
            //printf("F %d  %d %d  %d
    ",n/i,i,r,F(n/i));
        }
        return ans;
    }
    int main(){
        //freopen("in","r",stdin);
        a=read();b=read();
        sieve(sqrt(b)+1);
        printf("%lld",S(b)-S(a-1));
    }
    
    
    



  • 相关阅读:
    吴裕雄--天生自然ANDROID开发学习:4.1.2 Activity初窥门径
    吴裕雄--天生自然ANDROID开发学习:4.1.1 Activity初学乍练
    吴裕雄--天生自然ANDROID开发学习:3.8 Gestures(手势)
    吴裕雄--天生自然ANDROID开发学习:3.7 AsyncTask异步任务
    吴裕雄--天生自然ANDROID开发学习:3.6 响应系统设置的事件(Configuration类)
    吴裕雄--天生自然ANDROID开发学习:3.5 监听EditText的内容变化
    jquery: filter 过滤显示
    taro3.x: scrollX横向滚动
    taro3.x: subPackages分包处理解决包测试过大问题
    taro3.x: 查询组件封装
  • 原文地址:https://www.cnblogs.com/candy99/p/6367375.html
Copyright © 2011-2022 走看看