zoukankan      html  css  js  c++  java
  • HDU 2588 GCD(欧拉函数)

    思路:

    1.题意是给出nnmm,让我们找出有多少个x(1<=x<=n)x(1<=x<=n)满足gcd(n,x)>=mgcd(n,x)>=m
    2.设nnxx的最大公约数是dd,则我们可以将nnxx表示成
    {n=pdx=qd egin{cases} n=p*d\ x=q*d end{cases}
    且我们可以得知ppqq互质且q<=pq<=p,因此我们需要求出在此时dd确定的情况下有多少个qq存在即可,即求pp的欧拉函数;
    3.接着我们的目标就是求出对于每一个d(d>=m)d(d>=m),与之对应的pp的欧拉函数,最后将它们相加即可;
    4.可能有些人会有疑问(比如说我),题目问xx有多少种取值,我们就简单的遍历所有pp,将这些pp的欧拉函数相加就好了吗?不同的dd对应不同的pp,而同一个pp也对应许多不同的qq,有没有可能这些情况中,计算出来的xx值有重复?
    答案是不会的。我们来证明一下,假设
    {n=p1d1x1=q1d1n=p2d2x2=q2d2x1=x2 egin{cases} n=p1*d1\ x1=q1*d1\ n=p2*d2\ x2=q2*d2\ x1=x2 end{cases}
    则会有
    {p1d1=p2d2q1d1=q2d2 egin{cases} p1*d1=p2*d2\ q1*d1=q2*d2 end{cases}
    则有p1=p2q1q2p1=frac{p2*q1}{q2},此时q1q2q1 eq q2,因此必有q1q1的一个或多个质因子包含在p1p1中,这与q1p1q1p1互质相矛盾,因此xx的值不会重复;

    代码:

    #include<iostream>
    #include<vector>
    using namespace std;
    int n,m;
    vector<int> v;
    void cal_divisor(int n){  //which is greater than m or equals to m
    	for(int i=1;i*i<=n;i++) if(n%i==0){
    			if(i>=m) v.push_back(i);
    			if(i!=n/i&&n/i>=m) v.push_back(n/i); 
    	}
    }
    int eular(int n){
    	int ans=n;
    	for(int i=2;i*i<=n;i++) if(n%i==0){
    		ans-=ans/i;
    		while(n%i==0) n/=i;
    	}
    	if(n>1) ans-=ans/n;
    	return ans;
    }
    int solve(){
    	if(m==1) return n;
    	v.clear();
    	cal_divisor(n);
    	int ans=0;
    	for(auto x:v) ans+=eular(n/x);
    	return ans;
    }
    int main(){
    	int t; cin>>t;
    	while(t--){
    		cin>>n>>m;
    		cout<<solve()<<'
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    bzoj 2159 Crash 的文明世界
    bzoj 4241 历史研究
    数论大合集(柿子版)
    [IOI2005]mou
    CSP 2020 T3 函数调用
    线段树 --算法竞赛专题解析(24)
    树状数组 --算法竞赛专题解析(23)
    算法竞赛专题解析(22):数论--同余
    算法竞赛专题解析(21):数论--线性丢番图方程
    算法竞赛专题解析(20):数论--GCD和LCM
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308791.html
Copyright © 2011-2022 走看看