• 51nod 算法马拉松35 E


    有这样一段两两求最大公约数的程序CoGcd,

    int Gcd(int x, int y){
       if(y == 0)return x;
       return Gcd(y, x % y);
    }
    
    void CoGcd(int m){
       for(int i = 1; i <= m; i++)
           for(int j = 1; j <= m; j++)
               Gcd(i, j);
    }
    

    给出m的值,进行t次询问,每次询问包含一对xi,yi。针对每次询问,输出整个程序执行过程当中,Gcd(xi, yi)被执行了多少次。

    例如:(m = 20)

    (Gcd(8,5))会被执行4次,对应的x, y值是

    (8,5) (5,8) (13,8) (8,13),这4组x y,在调用Gcd时,会递归执行Gcd(8, 5)。

    sol

    考虑二元组((a,b))(a>b),在一次操作之后是该二元组一定是((ka+b,a))的形式。

    考虑二元组((a,a+b)),之后每次操作形如:

    [(x,y) o (x+y,y) \ (x,y) o (x,x+y) ]

    不难发现这样的操作与取模操作的逆运算一一对应(一个是让(k=k+1),另一个是换方向(k=1))。

    并且这样找出来的二元组不会重复。

    考虑用二元组(x,y)表示一个数(ax+(a+b)y)。显然合法的(x,y)是所有(gcd(x,y)=1)

    并且每一个((x,y))只会作为最大值出现2次。

    问题即求:

    [egin{aligned} sum _{x,y} [gcd(x,y)=1][ax+(a+b)yle m] \ =sum _d mu(d) sum _{x,y} [ax+(a+b)y le lfloorfrac {m}{d} floor] \ end{aligned} ]

    杜教筛 + 类欧几里得即可。

    复杂度(O(Tsqrt mlog m + m^frac 23))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 5e6+6;
    int mu[N], prime[N], pcnt, vis[N];
    inline void sieve(int n = 5e6){
    	mu[1] = 1;
    	for(int i=2;i<=n;i++){
    		if(!vis[i])prime[++pcnt]=i,mu[i]=-1;
    		for(int j=1;j<=pcnt&&1ll*i*prime[j]<=n;j++){
    			vis[i*prime[j]] = 1;
    			if(i%prime[j])mu[i*prime[j]] = -mu[i];
    			else {
    				mu[i*prime[j]]=0;
    				break;
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)mu[i] += mu[i-1];
    }
    ll query(ll n, ll a, ll b, ll c) {
    	ll x = a / c, y = b / c;
    	if (!a) {
    		return y * (n + 1);
    	}else if (a >= c || b >= c) {
    		return query(n, a % c, b % c, c) + n * (n + 1) / 2 * x + (n + 1) * y;
    	} else {
    		ll m = (1ll * a * n + b) / c;
    		return n * m - query(m - 1, c, c - b - 1, a);
    	}
    }
    map<int,int> MU;
    inline int q1(int n){
    	if(n<=5000000)return mu[n];
    	if(MU.find(n)!=MU.end())return MU[n];
    	int ans = 1;
    	for(int u=2,v;u<=n;u=v+1){
    		v=n/(n/u);
    		ans -= (v-u+1)*q1(n/u);
    	}
    	return MU[n]=ans;
    }
    inline ll q(int a,int b,int n){
    	int d = n/a;
    	int t = n%a;
    	return query(d-1,a,t,b);
    }
    ll ans = 0;
    int t,m;
    inline void find(int x,int y){
    	if(x>m||y>m)return;
    	ans+=2;
    	find(x+y,y),find(x,y+x);
    	
    }
    
    int main()
    {
    	cin >> t >> m;
    	sieve();
    	while(t--){
    		ans = 0;
    		int a,b;
    		scanf("%d%d",&a,&b);
    		if(a<=b){puts("1");continue;}
    		b+=a;
    		if(b>m){puts("2");continue;}
    		ans = 4;
    		for(int u=1,v;u<=m;u=v+1){
    			v=m/(m/u);
    			int f1 = q1(v) - q1(u-1);
    			ans += 4ll*f1*q(a,b,m/u);
    		}
    		printf("%lld
    ",ans);
    	}
    }
    
  • 相关阅读:
    Django高级编程之自定义Field实现多语言
    Python魔法方法__getattr__和__getattribute__详解
    Python深入浅出property特性属性
    Python中使用__new__实现单例模式并解析
    Python中类方法、__new__方法和__init__方法解析
    Python中可迭代对象、迭代器以及iter()函数的两个用法详解
    Docker ubuntu apt-get更换国内源解决Dockerfile构建速度过慢
    Python抽象基类中__subclasshook__方法的使用并实现自己的虚拟子类
    Scrapy-redis分布式爬虫爬取豆瓣电影详情页
    PHP5.5+ APC 安装
  • 原文地址:https://www.cnblogs.com/weiyanpeng/p/11623594.html
Copyright © 2020-2023  润新知