zoukankan      html  css  js  c++  java
  • Vijos1889 天真的因数分解

    描述

    小岛: 什么叫做因数分解呢?
    doc : 就是将给定的正整数n, 分解为若干个素数连乘的形式.
    小岛: 那比如说 n=12 呢?
    doc : 那么就是 12 = 2 X 2 X 3 呀.
    小岛: 呜呜, 好难, 居然素数会重复出现, 如果分解后每一个素数都只出现一次, 我就会.

    wish: 这样来说, 小岛可以正确分解的数字不多呀.
    doc : 是呀是呀.
    wish: 现在问题来了, 对于给定的k, 第 k 个小岛无法正确分解的数字是多少?

    格式

    输入格式

    输入只有一行, 只有一个整数 k.

    输出格式

    输出只有一行, 只有一个整数, 表示小岛无法正确分解出来的第k个数字.

    样例1

    样例输入1

     
    10

    样例输出1

     
    27

    限制

    对于30%的数据, k <= 2,000,000
    对于100%的数据, 1 <= k <= 10,000,000,000

    提示

    前 10 个小岛无法正确分解出来的数字依次是: 4 8 9 12 16 18 20 24 25 27

    莫比乌斯反演

    小于x的可以正确分解的数字个数是 Σmu[i]*(x/i^2),算不能分解正确的只要把mu反一下就行

    ↑可以参照这里http://www.cnblogs.com/SilverNebula/p/5656771.html

    AC记录喜+1

    然而1A记录并没有喜+1,因为二分上界傻傻写成了k……用脚想都知道不可能

    ↓这个二分上界是从黄学长那里看来的233

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<vector>
     8 #define LL long long
     9 using namespace std;
    10 const int mxn=200010;
    11 LL read(){
    12     LL x=0,f=1;char ch=getchar();
    13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 int pri[mxn],mu[mxn],cnt=0;
    18 bool vis[mxn];
    19 void init(){
    20     mu[1]=1;
    21     for(int i=2;i<mxn;i++){
    22         if(!vis[i]){
    23             pri[++cnt]=i;
    24             mu[i]=1;
    25         }
    26         for(int j=1;j<=cnt && (LL)pri[j]*i<mxn;j++){
    27             vis[pri[j]*i]=1;
    28             if(i%pri[j]==0){mu[pri[j]*i]=0;break;}
    29             mu[pri[j]*i]=-mu[i];
    30         }
    31     }
    32     return;
    33 }
    34 LL calc(LL x){
    35     int m=sqrt(x);
    36     LL res=0;
    37     for(int i=2;i<=m;i++)
    38         res+=x/((LL)i*i)*mu[i];
    39     return res;
    40 }
    41 int main(){
    42     int i,j;
    43     init();
    44     LL n=read();
    45     LL l=n,r=25505460948LL;
    46     LL ans;
    47     while(l<=r){
    48         LL mid=(l+r)>>1;
    49         if(calc(mid)>=n){ans=mid;r=mid-1;}
    50         else l=mid+1;
    51     }
    52     cout<<ans<<endl;
    53     return 0;
    54 }
  • 相关阅读:
    剑指Offer34 数组中的逆序对
    剑指Offer33 第一个只出现一次的字符
    剑指Offer32 丑数
    剑指Offer31 把数组排成最小的数
    剑指Offer30 从1到n整数出现1的个数
    剑指Offer29 连续子数组最大和
    剑指Offer28 最小的K个数(Partition函数应用+大顶堆)
    DNS的递归查询和迭代查询
    剑指Offer27 数组中超过一半的数
    剑指Offer26 字符串的全排列
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5656813.html
Copyright © 2011-2022 走看看