Code Forces 592 C. The Big Race(数论)

来源:互联网 发布:vb与vs的区别 编辑:程序博客网 时间:2024/04/30 15:57

Description
给出三个整数t,w,b,问在1~t中有多少个数num满足num%w=num%b
Input
三个整数t,w,b(1 ≤ t, w, b ≤ 5*1e18)
Output
输出1~t中满足num%w=num%b的num个数占的比例,以最简分数形式输出
Sample Input
10 3 2
Sample Output
3/10
Solution
当num< min(w,b)时显然num%w=num=num%b,此时有min(w,b)-1个数满足条件,令lcm=lac(w,b),gcd=gcd(w,b),那么t=(t/lcm)*lcm+t%lcm,对于余数部分t%lcm,ans+=min( min(w,b)-1,t%lcm ),对于每一个lcm段,由于lcm%w=0=lcm%b,故可以将一个lcm段中的num看作1~lcm,1~min(w,b)-1中有min(w,b)-1个数符合条件,min(w,b)~max(w,b)之间没有符合条件的数字,所以只需分析max(w,b)+1~lcm之间有多少符合条件的数字,设num=m*w+x=n*b+x,w=c*gcd,b=d*gcd,故有mc=nd,其中m<=d,n<=c,显然c,d互素,那么m%d=d%m=n%c=c%n=0,所以有m=d,n=c,因此满足条件的num只有一个,即lcm,那么每一个lcm段中就有min(w,b)个满足条件的数字,综合起来得到ans=(t/lcm)*min(w,b)+min(min(w,b)-1,t%lcm)
注意由于w和b过大,在计算时不知道lcm多大不能直接用t/lcm,而是先通过判断t/w*gcd/b是否为0来判断lcm是否超过t,如果超过就直接令ans=min(min(w,b)-1,t),否则再用上面的公式(此时t/lcm才有意义,因为lcm

#include<stdio.h>#define min(x,y) ((x)<(y)?(x):(y))typedef long long ll;ll gcd(ll a,ll b){    if(a<b) return gcd(b,a);    if(b) return gcd(b,a%b);    return a;}int main(){    ll t,w,b,lcm,ans,temp;    while(~scanf("%I64d%I64d%I64d",&t,&w,&b))    {        lcm=w/gcd(w,b)*b;        if(t/w*gcd(w,b)/b)            ans=(t/lcm)*min(w,b)+min((min(w,b)-1),(t%lcm));        else            ans=min((min(w,b)-1),t);        temp=gcd(ans,t);        printf("%I64d/%I64d\n",ans/temp,t/temp);    }    return 0;}
0 0
原创粉丝点击