scription
qwb同时也是是之江学院的志愿者,暑期要前往周边地区支教,为了提高小学生的数学水平。她把小学生排成一排,从左至右从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名学生报的数字是多少?
Input
多组测试数据,处理到文件结束。(测试数据数量<=8000)
每个测试例一行,每行有四个整数x,y,z,N。( 2≤x,y,z≤107,1≤N≤1017)。
Output
对于每个测试例,输出第N名学生所报的数字,每个报数占一行。
Sample Input
2 3 5 2
6 2 4 10000
Sample Output
7
19999
HINT
昨晚普遍状态:想法蜜汁快,然后迷之卡点,调试贼久,然后迷之ac。。。。
然后罚时爆炸- -。。还是觉得要多打打这种 不然心态稳不住
离散没学好 卡贼久。。。一个原因是我一开始只记得定理
三个互质的 x,y,z 才能这样这样容斥。后来想到三个不互质的用最小公倍数再容斥就好。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
return (b==0)?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
ll xx,yy,zz,hh;
long long x,y,z;
ll pan(ll mm)
{
ll res=0;
res=mm/x+mm/y+mm/z-mm/xx-mm/yy-mm/zz+mm/hh;
return mm-res;
}
int main()
{
long long n;
while(scanf("%lld%lld%lld%lld",&x,&y,&z,&n)!=EOF)
{
if(n==1)
{
printf("1\n");
continue;
}
xx=lcm(x,y);
yy=lcm(x,z);
zz=lcm(y,z);
hh=lcm(lcm(xx,yy),zz);
ll l=1,r=1e18;//右边界开小了
ll res=0;
while(l<=r){
ll mid=(l+r)>>1;
if(pan(mid)>n)
{
r=mid-1;
}
else if(pan(mid)<n)
{
l=mid+1;
}
else
{
res=mid;
r=mid-1;
}
}
printf("%lld\n",res );
}
}
/**************************************************************
Problem: 1481
User: ZJC2017Final378
Language: C++
Result: Accepted
Time:64 ms
Memory:1712 kb
****************************************************************/