首页 > 移动平台 > 详细

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

时间:2015-04-09 23:51:58      阅读:431      评论:0      收藏:0      [点我收藏+]

题目链接:点击打开链接

题意:

输入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 <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <vector>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
const int inf = 1e8;
const double eps = 1e-8;
const double pi = acos(-1.0);
template <class T>  
inline bool rd(T &ret) {  
    char c; int sgn;  
    if(c=getchar(),c==EOF) return 0;  
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();  
    sgn=(c=='-')?-1:1;  
    ret=(c=='-')?0:(c-'0');  
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');  
    ret*=sgn;  
    return 1;  
} 
template <class T> 
inline void pt(T x) { 
    if (x <0) { putchar('-');x = -x; }  
    if(x>9) pt(x/10);  
    putchar(x%10+'0');  
}
using namespace std;
typedef long long ll;
typedef pair<int,int> pii; 	
const int N = 1e5;
ll prime[N],primenum;//有primenum个素数 math.h
void PRIME(ll Max_Prime){
	primenum=0;
	prime[primenum++]=2;
	for(ll i=3;i<=Max_Prime;i+=2)
	for(ll j=0;j<primenum;j++)
		if(i%prime[j]==0)break;
		else if(prime[j]>sqrt((double)i) || j==primenum-1)
		{
			prime[primenum++]=i;
			break;
		}
}
ll l, k;
vector<ll>fac;
void factor(ll x){
	fac.clear();
	for(int i = 0; i < primenum && prime[i]*prime[i]<= x; i++)
	{
		if(x%prime[i])continue;
		fac.push_back(prime[i]);
		while(x%prime[i]==0)x/=prime[i];			
	}
	if(x!=1)fac.push_back(x);
//	cout<<x<<" " ;puts("factor:");	for(int i = 0; i < fac.size(); i++){
//		pt(fac[i]); puts("**");
//	}
}
ll solve(ll x){//计算与x有2个及以上的因子个数
	if(x<=0)return 0;
	if(x == 1)return 1;
	ll sum = 0, siz = (int)fac.size();
	for(int i = 1; i < (1<<siz); i++)
	{
		ll lcm = 1, one = 0;
		for(int j = 0; j < siz; j++)
			if(i & (1<<j))
			{
				lcm *= fac[j];
				one++;
			}
		if(one&1)
			sum += x/lcm;
		else sum -= x/lcm;
	}
	return x-sum;
}
int main(){
	PRIME(1e5+10);
	while(cin>>l>>k){
		factor(l);
		ll L = 1, R = 1e18, ans = 1;
		while(L <= R){
			ll mid = (L+R)>>1;
			ll ok = solve(mid);
			if(ok<k)L = mid+1;
			else {
				ans = mid;
				R = mid-1;
			}
		}
		pt(ans); puts("");
	}
    return 0;
}


solve(x) 实现:

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

原文:http://blog.csdn.net/qq574857122/article/details/44966333

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!