zoukankan      html  css  js  c++  java
  • hdu5297 Y sequence(容斥原理+迭代)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5297

    题意:给定整数n和整数r,在1、2、3、4、5.......的序列中删掉能够开2次方的数,3次方的数,4次方的数,.......r次方的数,剩下的数称为Y序列,求Y序列中第n个数是多少。

    分析:对于一个数x,假设求出x在Y序列的位置就好办了。

         先无论序列中的1,假如r=3,能够开2次方的数有4,9,16,25,36,49,64.....

                              能够开3次方的数有8,27,64.......

         我们把能够开2次方的数的个数减掉,再把能够开3次方的数的个数减掉,会发现减多了(把既能够开2次方又能够开3次方的数减了两次),然如把减多了的补回来,就要把能够开6次方的数的个数加回来,这样就能够想到容斥原理:先将全部的2~r的数里面的素数组合起来(那些有1个以上某个同样的因子的数不用考虑,之前肯定会被减掉),然后枚举这些数,看这些数的质因子为奇数和还是偶数个........

         得到x的位置后,開始想到用二分,没想到超时了,,,,,,看了一下别人的思路,用的是迭代...改成迭代就a了。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67};
    int cnt[100]={19,0,1,1,1,1,2,1,1,1,2,1,2,1,2,2,1,1,2,1,2,2,2,1,2,1,2,1,2,1,3,1,1,2,2,2,2,1,2,2
    ,2,1,3,1,2,2,2,1,2,1,2,2,2,1,2,2,2,2,2,1,3,1,2,2,1};
    long long considrt[6000000],nconsidrt;
    void GetConsider(int r)
    {
        nconsidrt=0;
        int i,j,sz;
        for(i=0;prime[i]<=r;i++)
        {
            sz=nconsidrt;
            for(j=0;j<sz;j++)
            {
                if(considrt[j]*prime[i]<=63)
                    considrt[nconsidrt++]=considrt[j]*prime[i];
            }
            considrt[nconsidrt++]=prime[i];
        }
    }
    
    long long cal(long long x)
    {
        long long ret(0);
        for(int i=0;i<nconsidrt;i++)
        {
            if(cnt[considrt[i]]&1)
                ret+=(long long)pow(x+0.5,1.0/considrt[i])-1;
            else
                ret-=(long long)pow(x+0.5,1.0/considrt[i])-1;
        }
        return x-ret-1;
    }
    
    long long solve(long long n,int r)
    {
        GetConsider(r);
        long long ans = n;
        while(1)
        {
            long long temp = cal(ans);
            if(temp == n)
                break;
            ans += n - temp; 
        }
        return ans;
    }
    int main()
    {
        int ncase,r;
        long long n;
        scanf("%d",&ncase);
        while(ncase--)
        {
            scanf("%I64d%d",&n,&r);
            printf("%I64d
    ",solve(n,r));
        }
        return 0;
    }


  • 相关阅读:
    VC常用代码
    richedit
    vc++ 2005 发布程序
    管道应用之捕获控制台程序信息
    黑客基础知识编程(转)
    Get All IE Info from win32 api
    vc 界面编程常用方法(http://blog.emuch.net/244485/spacelistblogitemtypeid2708.html)
    使用ADO调用存储过程
    在C#中如何实现文件夹的复制(转)
    C语言开发病毒程序(转)
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6738316.html
Copyright © 2011-2022 走看看