JZOJ1241. Number
来源:互联网 发布:win10网络受限怎么办 编辑:程序博客网 时间:2024/06/05 20:27
题目
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
分析
观察数据范围:
对于50%的数据是很简单的,只需要暴力。
而要通过后面的数据就有点小困难。
题解
很容易想到最后的答案肯定是A[]中间的某个数乘上一个整数。
看到K怎么大枚举每一个数很显然是不现实的。
我们考虑一下,可不可以把问题转换一下,
看一下可不可以变成一个判断问题。
- 看到K这么大,想到用二分。
现在问题就变成了求在区间[1..mid]有多少个符合条件的数。
- 有关整数倍数的问题很容易想到容斥原理。
code
#include <cstdio>#include <algorithm>#include <cstring>#include <string.h>#include <cmath>#include <stdlib.h>#include <math.h>#define ll long long using namespace std;ll a[20],l,r,ans,k,mid;int n,m;ll gcd(ll x,ll y){ if(x%y==0)return y;else return gcd(y,x%y);}void bfs(int x,ll sum,int deep){ if(sum>mid)return; if(deep%2)ans+=floor(mid/sum)*deep;else ans-=floor(mid/sum)*deep; for(int i=x+1;i<=n;i++) bfs(i,sum/gcd(sum,a[i])*a[i],deep+1);}int main(){ scanf("%d%lld",&n,&k); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); l=1; r=1000000000000000; while(l<r) { mid=(l+r)/2; ans=0; for(int i=1;i<=n;i++) bfs(i,a[i],1); if(ans<k)l=mid+1;else r=mid; } printf("%lld\n",l);}
1 0
- JZOJ1241. Number
- Number
- number
- number
- Number
- number
- number
- Number
- Number
- NUMBER
- Number
- Number()
- number
- Number
- Number
- E: number number number
- 1005 number number number
- HDU6198 number number number
- Activiti学习——整合ActivitiModeler到项目中
- Android HandlerThread 完全解析
- 树莓派下的基本命令和安装MySQL vim等
- Android NDK(二)最最简单的方法利用NDK实现MP3录音
- Android 百分比布局揭秘
- JZOJ1241. Number
- 获取系统的默认编码
- 同余与乘法逆元
- JAVA 的垃圾回收机制
- 6个Java项目UML反向工程工具
- HTTP请求和响应
- Java程序员修炼之道 之 Logging(2/3) - 怎么写Log
- 编译链接基本素养笔记(一)ELF文件结构
- 最大子段和