zoukankan      html  css  js  c++  java
  • bzoj 2440: [中山市选2011]完全平方数

    2440: [中山市选2011]完全平方数

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 4497  Solved: 2174
    [Submit][Status][Discuss]
    

    Description

    小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些
    数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而
    这丝毫不影响他对其他数的热爱。
    这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一
    个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了
    小X。小X很开心地收下了。
    然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?

    Input

    包含多组测试数据。文件第一行有一个整数 T,表示测试
    数据的组数。
    第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。

    Output

    含T 行,分别对每组数据作出回答。第 i 行输出相应的
    第Ki 个不是完全平方数的正整数倍的数。

    Sample Input

    4
    1
    13
    100

    1234567

    Sample Output

    1
    19
    163
    2030745

    HINT

    对于 100%的数据有 1 ≤ Ki ≤ 10^9, T ≤ 50

    Source

    这个题目需要用到莫比乌斯函数、二分答案、容斥原理

    做法:

    首先二分答案,问题转化为求(left[1,x ight])之间有多少个无平方因子数
    根据容斥原理可知,对于(sqrt(x))之内所有的质数,
    答案G(x)=0个质数平方倍数的个数-1个质数平方倍数的个数+2个质数平方倍数的个数-...,
    那么对于偶数个质数平方对于答案的贡献就是正的,否则是负的,如果不是若干个互异质数的乘积,那么对答案没有影响,
    如何表示这个式子呢?
    观察莫比乌斯函数的定义 ef{1},可以知道对于能对答案产生贡献的数(x)(mu(x)=(-1)^k),其中(k)(x)分解得到质数的个数
    根据上述说明,那么可以得知结果

    [G(x)=sum_{i=1}^{lfloor sqrt{x} floor}mu(i)lfloor frac{x}{i^2} floor ]

    第一次这么快AC一个题真是美滋滋
    在BZOJ上跑了4s多不算很快

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define N 100005
    #define inf 0x7fffffff
    using namespace std;
    
    bool not_prime[N];
    int prime[N];
    int mu[N];
    int tot;
    
    void Mu(int n){
        int i,j;
        mu[1]=1;
        for(i=2;i<=n;i++){
        	if(!not_prime[i]){
        		prime[++tot]=i;
        		mu[i]=-1;
        	}
    	    for(j=1;prime[j]*i<=n;j++){
    		    not_prime[prime[j]*i]=1;
                if(i%prime[j]==0){
        			mu[prime[j]*i]=0;
        			break;
        		}
    		    mu[prime[j]*i]=-mu[i];
    	    }
        }
    }    
    
    int can(int x){
        int sum=0;
        int s=floor(sqrt(x));
        for(int i=1;i<=s;++i)
            if(mu[i])
               sum+=mu[i]*floor(x/(i*i));
        return sum;
    }
    
    int main(){
        Mu(N);
        int T;
        scanf("%d",&T);
        while(T--){
            int num;
            scanf("%d",&num);
            long long l=1,r=num<<1,mid;
            while(l<r){
                mid=(l+r)>>1;
                if(can(mid)<num)
                    l=mid+1;
                else r=mid;
            }
            printf("%lld
    ",r);
        }
        return 0;
    }
    
  • 相关阅读:
    割点和割边
    差分约束
    错题本(持续更新)
    高中语文小说赏析问题
    CSPS2019游记
    【USACO09FEB】改造路Revamping Trails
    【SDOI2013】森林
    Nozaki_Chiyo的代码盒
    【HAOI2015】树上染色
    kruskal重构树
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/8011402.html
Copyright © 2011-2022 走看看