报数游戏-(容斥+二分)

来源:互联网 发布:英语四级真题软件 编辑:程序博客网 时间:2024/05/18 00:13

第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

伊苏比系列

伊苏比的梦幻之旅(三)

  

我们可以通过容斥定理计算出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大,如果比他大的话就不用管它了。

题解:http://www.cnblogs.com/cs-lyj1997/p/6852661.html

#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 1000005ll 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;elsel=m;}printf("%lld\n",r);return 0;}


0 0
原创粉丝点击