2017年第0届浙江工业大学之江学院程序设计竞赛决赛--A(二分法+容斥原理)
来源:互联网 发布:鼠标指针主题 知乎 编辑:程序博客网 时间:2024/06/08 22:40
Problem A: qwb与支教
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1606 Solved: 325
[Submit][Status][Web Board]
Description
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 26 2 4 10000
Sample Output
719999
HINT
想法:二分法+容斥原理
用二分法找1到1e18之间的任何数(mid是我们现在在找的那个数)
为了好说明我们用pw((x,y),mid)表示1到这个数有多少个数即是x的倍数又是y的倍数
容斥原理:
1到这个数有多少个数是(x,y,z)三个数的倍数=pw((x),mid)+pw((y),mid)+pw((z),mid)-pw((x,y),mid)-pw((y,z),mid)-pw((x,y,z),mid)+pw((x,y,z),mid)
公式:mid/x+mid/y+mid/z-mid/lcm(x,y)-mid/lcm(x,z)-mid/lcm(y,z)+mid/lcm(lcm(x,y),z)
注(lcm(x,y)为求最小公倍数)
那1到mid这个数中有多少个数是学生报的数字=mid-(mid/x+mid/y+mid/z-mid/lcm(x,y)-mid/lcm(x,z)-mid/lcm(y,z)+mid/lcm(lcm(x,y),z))
代码:
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <stdio.h>
typedef long long ll;
using namespace std;
ll gcd(ll x,ll y)//用欧几里得求最大公约数
{
return y==0?x:gcd(y,x%y);
}
ll lcm(ll x,ll y)//用最大公约数求最小公倍数
{
ll g=gcd(x,y);
return x/g*y;
}
ll x,y,z,n;
int check(ll mid)//容斥原理
{
ll res=mid-(mid/x+mid/y+mid/z-mid/lcm(x,y)-mid/lcm(x,z)-mid/lcm(y,z)+mid/lcm(lcm(x,y),z));
if(res>=n) return 1;
return 0;
}
int main()
{
while(~scanf("%lld %lld %lld %lld",&x,&y,&z,&n))
{
ll low=1,high=1e18,mid,ans;
while(low<=high)//二分法查找
{
mid=(low+high)/2;
if(check(mid)==1)
{
high=mid-1;
ans=mid;
}
else
low=mid+1;
}
printf("%lld\n",ans);
}
return 0;
}
#include <string>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <stdio.h>
typedef long long ll;
using namespace std;
ll gcd(ll x,ll y)//用欧几里得求最大公约数
{
return y==0?x:gcd(y,x%y);
}
ll lcm(ll x,ll y)//用最大公约数求最小公倍数
{
ll g=gcd(x,y);
return x/g*y;
}
ll x,y,z,n;
int check(ll mid)//容斥原理
{
ll res=mid-(mid/x+mid/y+mid/z-mid/lcm(x,y)-mid/lcm(x,z)-mid/lcm(y,z)+mid/lcm(lcm(x,y),z));
if(res>=n) return 1;
return 0;
}
int main()
{
while(~scanf("%lld %lld %lld %lld",&x,&y,&z,&n))
{
ll low=1,high=1e18,mid,ans;
while(low<=high)//二分法查找
{
mid=(low+high)/2;
if(check(mid)==1)
{
high=mid-1;
ans=mid;
}
else
low=mid+1;
}
printf("%lld\n",ans);
}
return 0;
}
优化代码:
#include <iostream>
#include<cstdio>
#include <algorithm>
#define MAXN 1e18
using namespace std;
long long lcm(long long a,long long b)
{
long long ans=a/__gcd(a,b);
if(MAXN/ans<b) return 0;
return ans*b;
}
int main(void)
{
long long t,ans,mid,left,right,x,y,z,n;
while (~scanf("%lld%lld%lld%lld",&x,&y,&z,&n))
{
left=0,right=MAXN;
while(left<right-1)
{
mid=(left+right)/2;
ans=mid/x+mid/y+mid/z-mid/lcm(x,y)-mid/lcm(y,z)-mid/lcm(x,z);
t=lcm(lcm(x,y),z);
if(t) ans+=mid/t;
if(mid-ans>=n)
right=mid;
else
left=mid;
}
printf("%lld\n",right);
}
return 0;
}
#include<cstdio>
#include <algorithm>
#define MAXN 1e18
using namespace std;
long long lcm(long long a,long long b)
{
long long ans=a/__gcd(a,b);
if(MAXN/ans<b) return 0;
return ans*b;
}
int main(void)
{
long long t,ans,mid,left,right,x,y,z,n;
while (~scanf("%lld%lld%lld%lld",&x,&y,&z,&n))
{
left=0,right=MAXN;
while(left<right-1)
{
mid=(left+right)/2;
ans=mid/x+mid/y+mid/z-mid/lcm(x,y)-mid/lcm(y,z)-mid/lcm(x,z);
t=lcm(lcm(x,y),z);
if(t) ans+=mid/t;
if(mid-ans>=n)
right=mid;
else
left=mid;
}
printf("%lld\n",right);
}
return 0;
}
阅读全文
0 0
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛--A(二分法+容斥原理)
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛 A: qwb与支教 [容斥]【数学】
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—A
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—A
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛 A.qwb与支教【二分+简单容斥】
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛 Problem A: qwb与支教(容斥+二分)
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—A qwb与支教
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—B
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—D
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—F
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—G
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—K
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—I
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛部分题解
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—E
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—J
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—C
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—H
- datatable分页增加首页和尾页
- javascript中变量的类型转换
- eclipse启动时报错java was started but returned exit code=13
- docker使用
- 区块链简介
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛--A(二分法+容斥原理)
- Bluetooth之BluetoothDevice
- uC/OS-III之信号量
- Java代码优化(转载)
- ubuntu14.04安装Django
- Centos7 修改mysql指定用户的密码
- ASP.NET-图形显示类控件
- 浏览器域名解析步骤
- [Hackerrank题目选做] Random Number Generator 二分+数学+猜结论