UVAlive 4683 Find The Number

来源:互联网 发布:大数据怎么快速学 编辑:程序博客网 时间:2024/05/17 05:56

题目链接: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 %100000007int 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;}


0 0
原创粉丝点击