[二分+容斥原理] poj 2773 Happy 2006

题目链接:

http://poj.org/problem?id=2773


Happy 2006

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 9131   Accepted: 3073

Description

Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9...are all relatively prime to 2006.

Now your job is easy: for the given integer m, find the K-th element which is relatively prime to m when these elements are sorted in ascending order.

Input

The input contains multiple test cases. For each test case, it contains two integers m (1 <= m <= 1000000), K (1 <= K <= 100000000).

Output

Output the K-th element in a single line.

Sample Input

2006 1
2006 2
2006 3

Sample Output

1
3
5

Source

POJ Monthly--2006.03.26,static

[Submit]   [Go Back]   [Status]  
[Discuss]

题目意思:

求与m互质的第k大的数

解题思路:

二分+容斥原理

二分出要求的数i,用容斥原理求出1~i之间的与m互质的数的个数kk,如果kk<k扩大范围,如果kk>k扩大范围,如果kk=k并且gcd(i,m)=1说明刚好找到,否则继续缩小范围。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define N 1000
bool isp[N+10];
int pri[N+10],pp[N+10],cnt,cnt0;
int m,k;
ll res;

void init()  //打出1000内的质数
{
    cnt=0;
    for(int i=1;i<=N;i++)
        isp[i]=true;

    for(int i=2;i<=N;i++)
    {
        if(isp[i])
        {
            pri[++cnt]=i;
            for(int j=i*2;j<=N;j+=i)
                isp[j]=false;
        }
    }
}
void Cal(int cur) //对cur分解质因数
{
    cnt0=0;

    for(int i=1;pri[i]*pri[i]<=cur;i++)
    {
        if(!(cur%pri[i]))
        {
            pp[++cnt0]=pri[i];
            while(!(cur%pri[i]))
                cur/=pri[i];
        }
    }
    if(cur!=1)
        pp[++cnt0]=cur;
}

void dfs(ll hav,int cur,int num,ll va) //容斥原理求出与m互质的且小于va的数的个数
{
    if(cur>cnt0||(hav>va))
        return ;
    for(int i=cur;i<=cnt0;i++)
    {
        ll temp=hav*pp[i];

        if(num&1)
            res-=va/temp;
        else
            res+=va/temp;
        dfs(temp,i+1,num+1,va);
    }
}
void solve(ll cur) //求出1~cur间与m互质的数的个数
{
    res=cur;

    for(int i=1;i<=cnt0;i++)
    {
        res-=cur/pp[i];
        dfs(pp[i],i+1,2,cur);
    }
}
ll gcd(ll a,ll b) //求最大公约数
{
    if(a%b==0)
        return b;
    return gcd(b,a%b);
}
int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   init();
   while(~scanf("%d%d",&m,&k))
   {
       ll ans,l,r,mid;

       l=1,r=(1LL<<62LL); //初始化一个很大的数
       Cal(m);

       while(l<=r)
       {
           mid=(l+r)>>1;
           solve(mid);
           ll temp=res; //个数

           //printf("mid:%I64d res:%I64d\n",mid,res);
           //system("pause");

           if(temp<k) //放大
                l=mid+1;
           else if(temp==k)
           {
               if(gcd(mid,m)==1) //最后一个刚好是与m互质的,说明恰好找到
               {
                   ans=mid;
                   break;
               }
               r=mid-1; //否则继续缩小
           }
           else
                r=mid-1;
       }
       printf("%I64d\n",ans);
   }
   return 0;
}

[二分+容斥原理] poj 2773 Happy 2006

时间: 2024-10-20 05:12:18

[二分+容斥原理] poj 2773 Happy 2006的相关文章

POJ 2773 Happy 2006

Happy 2006 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 9170   Accepted: 3092 Description Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9...are al

poj 2773 Happy 2006(欧拉函数应用)

http://poj.org/problem?id=2773 题意:输入n,k,求与n不互素的第k个数,k可能大于n. 思路:以n=6为例,与6互素的数有一定规律.{1,5},{7,12},{13,18}......,发现在[1,n],[n+1,n*2]......[m*n+1,(m+1)*n]区间内素数个数相同,且对应位置的数都相差n的整数倍.因此只要求出[1,n]内的与n互素的数即可.这个过程没必要一个一个枚举,可以用欧拉函数解决.因为欧拉函数已经求出了n的所有质因子,与n不互素的数都与n有

POJ 2773 Happy 2006#素数筛选+容斥原理+二分

http://poj.org/problem?id=2773 说实话这道题..一点都不Happy好吗 似乎还可以用欧拉函数来解这道题,但正好刚学了容斥原理和二分,就用这个解法吧. 题解:要求输出[1,m]中与m互质的第k个数,先打表,找到m的所有质因数,然后用二分实现,最开始区间为[1,2^60],利用容斥原理去找区间[1,mid]内素数的个数t,不断进行二分,直到所查找的区间[l,r]内素数的个数t等于k,mid=l=r,则此时的l就是第k个与m互质的数. #include<iostream>

POJ 2773 Happy 2006 (分解质因数+容斥+二分 或 欧几里德算法应用)

Happy 2006 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 10309   Accepted: 3566 Description Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9...are a

POJ 2773 Happy 2006 (二分答案+容斥)

题目链接:http://poj.org/problem?id=2773 题意: 求第k个与m互质的数: 分析: 很明显随着数的增大与m互质的数就越多,因此我们可以二分答案, 中间需要用到容斥原理求[1,mid]内与m互质的数的个数: 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <vector> using namespace std; const int ma

POJ 2773 Happy 2006【容斥原理】

题目链接: http://poj.org/problem?id=2773 题目大意: 给你两个整数N和K,找到第k个与N互素的数(互素的数从小到大排列),其中 (1 <= m <= 1000000,1 <= K <= 100000000 ). 解题思路: K很大,直接从小到大枚举找出不现实,只能二分答案.二分枚举[1,INF]范围内所有的数x, 找到1~x范围内与N互素的数个数,如果等于K,则就是结果. 然后考虑1~x范围内与N互素的数个数 = x - 1~x范围内与N不互素的数个

POJ 2773 Happy 2006 二分+容斥(入门

题目链接:点击打开链接 题意: 输入n ,k 求与n互质的第k个数(这个数可能>n) 思路: solve(mid)表示[1,mid]中有多少个和n互质,然后二分一下最小的mid 使得互质个数==k solve(x) 实现: 与n互质的个数=所有数-与n不互质的数=所有数-(与n有一个因子-与n有2个因子的+与n有3个因子的) 状压n的因子个数,然后根据上面的公式容斥得到. #include <stdio.h> #include <iostream> #include <

POJ 2773 Happy 2006(欧几里德算法)

题意:给出一个数m,让我们找到第k个与m互质的数. 方法:这题有两种方法,一种是欧拉函数+容斥原理,但代码量较大,另一种办法是欧几里德算法,比较容易理解,但是效率很低. 我这里使用欧几里德算法,欧几里德算法又名辗转相除法,原先单纯的用于求最大公约数,这里也算是一个小小的拓展应用,这个题利用的欧几里德算法的重要性质,假如a与b互质,那么b*t+a与b也一定互质,那样我们可以枚举1-m之间所有符合条件的数,然后打一个表格,求出所有符合条件的数,正如下表中的(5,5)所示,这个表格是一个带有周期性的自

[容斥原理] poj 3094 Sky Code

题目链接: http://poj.org/problem?id=3904 Sky Code Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1334   Accepted: 405 Description Stancu likes space travels but he is a poor software developer and will never be able to buy his own spacecraf