JZOJ.1241. Number
2016-07-12 16:22
381 查看
Problem
Description
有N(2<=N<=15)个数A1,A2,….,An-1,An,如果在这N个数中,有且仅有一个数能整除m,那么整数m就是一个幸运数,你的任务就是在给定A1,A2,….,An-1,An的情况下,求出第k小的幸运数。Input
第一行为一整数数N,K(2<=N<=15,1<=K<=2^31-1),意义如上述。接下来一行有N个整数,A1,A2,….,An-1,An,这N个整数均不超过2^31-1。
Output
输出一行,仅包含一个整数ans,表示第K小的幸运数。答案保证不超过10^15。Sample Input
输入1:2 4
2 3
输入2:
2 100
125 32767
Sample Output
输出1:8
输出2:
12500
Hint
对于50%的数据,N<=5,ANS<=100000对于80%的数据,N<=10,ANS<=10^15
对于100%的数据,N<=15,ANS<=10^15
Solution
正解:二分+容斥二分答案mid,现在就是要求在[1,mid]这个范围内,幸运数的个数Si。
则总个数为Σni=1mida[i]
如果它小于k则mid要增大,否则减小。
但是,这里面一定多算了很多的数。比如说序列{2,3}其中6不是幸运数,2这里算了一次,3这里又算了一次,所以个数要-2.(6是2,3的交集,所以我们要减去2和3的交集)
由容斥原理得,对于一个集合,如果集合元素个数为基数,则加上这个集合所有元素的LCM*集合元素个数否则减去。
由于N<=15,我们可以用2n 的时间来查找所有的集合。
总时间复杂度为O(log(1015)∗2n∗算LCM的时间).
Code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #define fo(i,a,b) for(i=a;i<=b;i++) #define LL long long using namespace std; LL a[20],l,mid,r,ans,sum; int i,n,k; LL gcd(LL a,LL b) { if (b==0) return a;else return gcd(b,a%b); } LL lcm(LL a,LL b) { if (a>b) swap(a,b); return a*b/gcd(a,b); } void select(LL x,LL s,LL cnt) { if (x>n) { if (cnt>0) { if (cnt%2==1) ans+=(mid/s)*cnt; else ans-=(mid/s)*cnt; } return; } LL w; select(x+1,s,cnt); w=lcm(s,a[x]); if (w>mid) return; //特别注意:如果LCM超过了mid要退出去,否则会爆炸。 select(x+1,w,cnt+1); } int main() { scanf("%d%d",&n,&k); fo(i,1,n) scanf("%lld",&a[i]); l=1; r=1000000000000000; while (l<r) { mid=(l+r)/2; ans=0; select(1,1,0); if (ans<k) l=mid+1;else r=mid; } printf("%lld",l); }
——2016.7.12
相关文章推荐
- 线程池(VC_Win32)
- 线程与多线程
- Java中基本类型和字符串之间的转换
- Blob对象和FileReader接口
- 树(Tree)
- Java Object 对象拷贝
- 【字符集及字符编码】UTF-8、UTF-16和UTF-32
- 问题小记
- JPA学习笔记(9)——映射双向一对多关联关系
- hdu1312 red and black(BFS)
- MongoDB备份恢复
- Linux驱动子系统之I2C(2)
- 正则表达式对照表
- Tkinter教程之Event篇(3)
- java程序的耦合度是什么
- 关于组织学生参加第八届全国大学生数学竞赛江西赛区竞赛的通知
- hdu1257
- iOS中4种判断网络请求的方式(系统状态栏、AFNetworking、Reachability、自定义)
- 20160712_生活化的工作, 工作化的生活
- 深入了解viewport和px