zoukankan      html  css  js  c++  java
  • 联赛模拟测试20 A. Simple (数学)

    题目描述


    分析

    这一道题和小凯的疑惑那一道题比较像
    对于两个数 (a,b),如果 (gcd(a,b)=1) ,那么它们不能表示的最大的数是 (a imes b -a -b)
    对于大于 (a imes b -a -b) 的数,都可以表示出来
    那么我们现在的问题就是求出小于等于 (a imes b -a -b) 的数中不能被表示出来的数的个数
    观察数据范围,我们可以发现这两个数中一个是 (10^9) 级别的,另一个是 (10^5) 级别的
    我们就可以从这里去找突破口,把序列依次划分为若干块,其中每一块的长度为 (b)

    我们分别求出 ([0,a*b-a-b]) ([b,a*b-a-b]) ([2b,a*b-a-b]) ...中可以用 (a,b) 表示的数的个数
    这样的数的数量为 (sum_{i=0}^{i*b<=a*b-a-b}((a*b-a-b-i*b)/a+1))
    因为 (a,b) 是互质的,所以这样划分不会重复
    我们拿最大值减去合法的方案就是不合法的方案
    对于 (a,b) 不互质的情况,我们把 (a,b,q) 同时除以 (gcd(a,b))
    这样的出的合法的方案数显然是相同的,因为去掉的都是不合法的方案
    时间复杂度 (O(n imes t))

    代码

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    typedef long long ll;
    int t;
    ll a,b,q,ans,now,mmax,haha,ha;
    ll gcd(ll aa,ll bb){
    	if(bb==0) return aa;
    	return gcd(bb,aa%bb);
    }
    int main(){
    	freopen("simple.in","r",stdin);
    	freopen("simple.out","w",stdout);
    	scanf("%d",&t);
    	while(t--){
    		ans=0;
    		scanf("%lld%lld%lld",&a,&b,&q);
    		if(a==b){
    			printf("%lld
    ",q-q/a);
    			continue;
    		}
    		now=gcd(a,b);
    		a/=now,b/=now;
    		haha=a*b-a-b;
    		mmax=std::min(haha,q/now);
    		if(a>b) std::swap(a,b);
    		for(ll i=1;i*b<=mmax;i++){
    			ans+=(mmax-i*b)/a;
    		}
    		ans+=mmax/a;
    		ans+=mmax/b;
    		if(now==1){
    			ans=mmax-ans;
    			printf("%lld
    ",ans);
    		} else {
    			if(q/now>=haha) ans=ans+(q/now-haha);
    			ans=q-ans;
    			printf("%lld
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Golang gRPC学习(01): gRPC介绍
    MySQL InnoDB存储引擎大观
    SpringBoot学习-图文并茂写Hello World
    Golang的goroutine协程和channel通道
    业务 产品 技术的一点看法
    需求一直做不完,怎么办?
    技术管理:项目开发中的几种风险管理
    go内存管理
    etcd实现分布式锁分析
    强缓存与协商缓存
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/13854970.html
Copyright © 2011-2022 走看看