HDU 2588 GCD(欧拉函数)

21 篇文章 0 订阅

思路:

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

代码:

#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()<<'\n';
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值