• CF267A 【Subtractions】


    题目大意:

    给你两个数 (a) , (b) ( (a) , (b) (le) (10^9) ),每次用大的减去小的,问当某个数为 (0) 时,一共减了多少次。

    思路:

    假设 (a) 为大的数,(b) 为小的数,且两数相差很大
    那么 (a) 最后可能会变成 (a-b-b-...-b)
    (-b-b-...-b) 合并,就可以得到 (- k imes b(k imes b le a)(a-k imes b < b))
    这个 (k) 其实就是 (a) 整除 (b) 的结果 。
    所以
    (a-b-b-...-b = a-k imes b = a-(lfloor frac{a}{b} floor) imes b = amod b)
    所以每次 (a) 最终都会变成 (amod b),变化次数即 (lfloor frac{a}{b} floor)
    可以用类似 (gcd) 的辗转相除法来完成。
    复杂度和 (gcd) 一样,都是 (O(log n)) 的。

    Code:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    
    using namespace std;
    
    LL read()
    {
    	LL ans=0,f=1;
    	char c=getchar();
    	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    	return ans*f;
    }
    
    int n,a,b;
    
    inline int get(int x,int y);
    
    int main()
    {
    	n=read();
    	while(n--)
    	{
    		a=read();b=read();
    		printf("%d
    ",get(a,b));
    	}
    	return 0;
    }
    
    //用类似 gcd 的辗转相除法
    //x 为大数,y 为小数
    //如果刚开始 x < y ,那么在一次操作后,x 与 y 将互换
    inline int get(int x,int y)
    {
    	if(!y)  如果小的数为 0 ,那么操作已经完成,返回 0
    		return 0;
    	// 否则将大数设为 y ,小数设为 x % y ( y > x % y )
    	// 并把变化次数 x / y 加入答案
    	return get(y,x%y)+x/y;
    }
    
  • 相关阅读:
    Windows10 JDK1.8安装及环境变量配置
    Adobe Premiere Pro 2020破解教程
    如何消除任务栏系统更新失败的图标
    微服务架构-Gradle下载安装配置教程
    第十五次-语法制导的语义翻译
    第十四次——算符优先分析
    第09组 Alpha冲刺(4/4)
    第09组 Alpha冲刺(3/4)
    第09组 Alpha冲刺(2/4)
    第09组 Alpha冲刺(1/4)
  • 原文地址:https://www.cnblogs.com/blackbird137/p/13550364.html
Copyright © 2020-2023  润新知