第10-3关 报数游戏(大数据)
发布时间: 2017年5月14日 16:04 最后更新: 2017年5月14日 16:06 时间限制: 1000ms 内存限制: 128M
伊苏比前往北极村支教,北极村共有N只北极熊。于是伊苏比让这些北极熊玩报数游戏。N只北极熊站成一排,从左至右从1开始依次往上报数。玩完一轮后,伊苏比发现这个游戏太简单了。于是她选了3个不同的数x,y,z;从1依次往上开始报数,遇到x的倍数、y的倍数或z的倍数就跳过。如果x=2,y=3,z=5;第一只报1,第2只得跳过2、3、4、5、6,报7;第3只得跳过8、9、10,报11.请你来计算,第N只北极熊报的数字是多少?
四个整数x,y,z,N.
第N只北极熊所报的数字。
2 3 5 2
7
6 2 4 10000
19999
数据范围:2≤x,y,z≤10^7,1≤N≤10^17
伊苏比系列
C (GCC 4.8) C++ (G++ 4.3) Java (Oracle JDK 1.7)
我们可以通过容斥定理计算出1-q之间有多少个数会被报到(不是x,y,z任何一个数的倍数),直接计算不是其倍数的数不好计算。可以计算出是x,y,z中一个数的倍数的数的个数。计算公式为S=q/x+q/y+q/z-q/gcd(x,y)-q/gcd(y,z)-q/gcd(z,x)+q/gcd(x,y,z);q-S就是报到的数。然后我们可以通过二分的方式找出最早报出N个数的q值,就是本题的答案。注意x,y,z均为10^7,直接乘会爆long long,就得用相除的方式判断一下gcd(x,y,z)是否比10^18大,如果比他大的话就不用管它了。
#include <stdio.h>
#include <string.h>
#include<functional>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
typedef long long ll;
#define maxn 1000005
ll gcd(ll x,ll y)
{
if(y==0)
return x;
return gcd(y,x%y);
}
ll lcm(ll a,ll b)
{
ll res,t;
res=a/gcd(a,b);
t=1000000000000000000/res;
if(t<b)//如果超线,不管他就好了
return -1;
res*=b;
return res;
}
int main(void)
{
ll x,y,z,b,i,l,r,m,xy,yz,xz,xyz,n;
scanf("%lld%lld%lld%lld",&x,&y,&z,&n);
l=0;r=1000000000000000000;
while(l+1<r)
{
ll ans=0;
m=(l+r)/2;
ans+=(m/x+m/y+m/z);
xy=lcm(x,y);
yz=lcm(y,z);
xz=lcm(x,z);
xyz=lcm(xy,z);
ans-=(m/xy+m/xz+m/yz);
if(xyz!=-1)
ans+=m/xyz;
/*if(m-ans==n)
{
printf("%lld\n",m);
return 0;
}*/
if(m-ans>=n)
r=m;
else
l=m;
}
printf("%lld\n",r);
return 0;
}