您的位置:首页 > 其它

UVAlive 4683 Find The Number

2016-03-31 21:29 417 查看
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=14336

题意:给一个含k个数的集合,符合条件的数当且仅当满足被集合中的一个数整除,求最小区间上界x,使得[1,x]内含有n个符合条件的数。



思路:二分答案+dfs容斥,如果用二进制枚举会超时。如果当前的倍数k是由x个数得到的,那么会有(n/k)个数之前会被那x个数单独都统计进去一次,所以是(n/k)*x。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007

int T;
int p[15];
int m;
LL k;
LL ans;

LL gcd(LL a , LL b)
{
return (a%b==0)?b:gcd(b,a%b);
}

void dfs(int now , int num , LL lcm , LL n)
{
if ( lcm > 1e15 ) return;
if ( num & 1 )
ans+=n/lcm*num;
else ans-=n/lcm*num;
rep(i,now+1,m)
dfs( i , num+1 , lcm/gcd(lcm,p[i])*p[i] , n );
}

int main()
{
cin>>T;
while(T--)
{
scanf("%d %lld",&m,&k);
rep(i,1,m) scanf("%d",p+i);
LL L = 1;
LL R = 1e15;
LL mid;
while(L<R)
{
ans = 0;
mid = (L+R)>>1;
rep(i,1,m)
dfs(i,1,p[i],mid);

if ( ans >= k )
R = mid;
else
L = mid + 1;
}
cout<<L<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: