• 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;
    }
    
  • 相关阅读:
    validFrom不通过submit按钮来触发表单验证
    微信小程序组件开发
    css3 单行文字溢出,多行文字溢出
    表格布局
    对象设置默认属性
    按钮样式
    判断一个json是否为空
    vue高仿饿了么(三)
    Win10 用IE打开网址默认跳转到Edge如何解决?
    VMware虚拟机安装Win11正式版
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308790.html
Copyright © 2020-2023  润新知