zoukankan      html  css  js  c++  java
  • BZOJ#2440. 完全平方数


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

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 5134  Solved: 2497

    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


    problem:
    求第k小不是完全平方数的数

     


    solution:

    任何一个数都可以化成多个质因子相乘的形式
    那么一个完全平方数的倍数肯定至少有两个质因子是相等的

    我们设n以内的非完全平方数倍数的个数为ans
    ans=n-完全平方数的个数

    想一想完全平方数倍数的个数怎么计算?
    发现我们只用找出2,3,5,7..质数的完全平方数倍数的个数就可以了,因为所有数都由他们组成
    -n/(2*2)-n/(3*3)-n/(5*5)....
    但我们发现会重复减一些数
    于是容斥一下
    减含奇数个质数的完全平方数倍数的个数,加上含偶数个质数的完全平方倍数的个数(所有质因子都不相同,因为如果有相同肯定是其倍数,我们会在之前就减去掉的)

    于是我们发现它们加减规则和μ的规则一样
    于是二分进行查找


    附上代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e4+12;
    int prime[N],cnt,vis[N],mu[N];
    long long ans=0;
    void getmu()
    {
        mu[1]=1;
        for(int i=2;i<=N;i++) 
        {
            if(!vis[i]) prime[++cnt]=i,mu[i]=-1;//注意mu赋初值 
            for(int j=1;j<=cnt;j++) 
            {
                if(prime[j]*i>N) break;
                vis[prime[j]*i]=1;
                if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
                else mu[i*prime[j]]=-mu[i];
            }
        }
    }
    long long check(long long mid) 
    {
        long long res=0;
        long long t=sqrt(mid);
        for(int i=1;i<=t;i++) 
        res+=mid/(i*i)*mu[i];
        return res;
    }
    int main()
    {
        freopen("a.in","r",stdin);
        getmu();
        int T;
        scanf("%d",&T);
        while(T--) 
        {
            long long k;scanf("%lld",&k);
            long long l=k,r=1644934081,ans=0; 
            while(l<=r) 
            {
                long long mid=(l+r)>>1;
                if(check(mid)>=k) ans=mid,r=mid-1;
                else l=mid+1;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }

  • 相关阅读:
    jython resources
    Installing a Library of Jython ScriptsPart of the WebSphere Application Server v7.x Administration Series Series
    jython好资料
    ulipad install on 64bit win7 has issue
    an oracle article in high level to descibe how to archtichre operator JAVA relevet project
    table的宽度,单元格内换行问题
    Linux常用命令大全
    dedecms系统后台登陆提示用户名密码不存在
    登录织梦后台提示用户名不存在的解决方法介绍
    Shell常用命令整理
  • 原文地址:https://www.cnblogs.com/Heey/p/9085164.html
Copyright © 2011-2022 走看看