[HDU2588]GCD 欧拉函数
2017-08-24 21:09
260 查看
题目链接:Hdu2588
—————————————-
给定两个正整数n和m,(2≤n≤1000000000,1≤m≤n),问有多少个x满足1≤x≤n 且 gcd(n,x)≥m。题目有多组数据。
—————————————-
我们发现,上式能产生贡献的i均大于m,能产生贡献的gcd(n,i)均为n的约数。
所以我们可以只枚举n大于等于m的约数d,再判断1~n中有多少个数与n的最大公约数为d。
即:Ans=∑m≤d≤n, d|n∑i=1n [gcd(n,i)=d].
这时我们发现,中括号里的表达式值为1时,i一定是d的倍数,所以我们进一步转化:∑m≤d≤n, d|n∑i=1n [gcd(n,i)=d]= ∑m≤d≤n, d|n∑i=1n[gcd(nd,id)=1]×[d|i].
由于i一定是d的倍数,所以id的取值范围是1~nd,所以上式中∑ni=1[gcd(nd,id)=1]×[d|i] 实际上就是在统计1~nd中与nd互质的数的个数,其实就是φ(nd).
至此,我们将式子转化成:∑m≤d≤n, d|n∑i=1n[gcd(nd,id)=1]×[d|i]=∑m≤d≤n, d|nφ(nd).
只需要O(n√)枚举满足条件的约数d,再O(n√−−−√)计算φ(nd)即可,总复杂度O(n√⋅n√−−−√).
—————————————-
—————————————-
—————————————-
——wrote by miraclejzd
—————————————-
概述
题目大意如下。给定两个正整数n和m,(2≤n≤1000000000,1≤m≤n),问有多少个x满足1≤x≤n 且 gcd(n,x)≥m。题目有多组数据。
—————————————-
题解
将题目待求的答案设为Ans,则:Ans=∑i=1n[gcd(n,i)≥m].我们发现,上式能产生贡献的i均大于m,能产生贡献的gcd(n,i)均为n的约数。
所以我们可以只枚举n大于等于m的约数d,再判断1~n中有多少个数与n的最大公约数为d。
即:Ans=∑m≤d≤n, d|n∑i=1n [gcd(n,i)=d].
这时我们发现,中括号里的表达式值为1时,i一定是d的倍数,所以我们进一步转化:∑m≤d≤n, d|n∑i=1n [gcd(n,i)=d]= ∑m≤d≤n, d|n∑i=1n[gcd(nd,id)=1]×[d|i].
由于i一定是d的倍数,所以id的取值范围是1~nd,所以上式中∑ni=1[gcd(nd,id)=1]×[d|i] 实际上就是在统计1~nd中与nd互质的数的个数,其实就是φ(nd).
至此,我们将式子转化成:∑m≤d≤n, d|n∑i=1n[gcd(nd,id)=1]×[d|i]=∑m≤d≤n, d|nφ(nd).
只需要O(n√)枚举满足条件的约数d,再O(n√−−−√)计算φ(nd)即可,总复杂度O(n√⋅n√−−−√).
—————————————-
代码
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #define ll long long #define For(i,j,k) for(register ll i=j; i<=(ll)k; ++i) #define Forr(i,j,k) for(reggister ll i=j; i>=(ll)k; --i) #define INF 0x3f3f3f3f using namespace std; ll T, n, m, phi, Ans; inline ll get_phi(ll x){ ll back = x; for(register ll i=2; i*i <= x; ++i) if(x%i == 0){ back = back/i*(i-1); while(x%i == 0) x /= i; } if(x != 1) back = back/x*(x-1); return back; }//质因数分解求欧拉函数。 int main(){ scanf("%lld", &T); while(T --){ scanf("%lld%lld", &n, &m); Ans = 0; for(ll di=1; di*di<=n; ++di) if(n%di == 0){//枚举约数n/d。 ll d = n/di; //计算d。 if(d < m) break;//考虑到我们得到的d是单调递减的,假如当前d不满足条件,直接退出。 phi = get_phi(di); Ans += phi;//计算答案 if(d*d == n) continue;//特判d为根号n的情况。 if(di >= m){ phi = get_phi(d); Ans += phi;//假如n/d也满足条件,计算答案。 } } printf("%lld\n", Ans); } return 0; }
—————————————-
小结
本题重点在于gcd和欧拉函数之间的转化,将枚举gcd(n,i)=d 转变成枚举与nd互质的数是关键,偷换概念也是很实用的方法。—————————————-
——wrote by miraclejzd
相关文章推荐
- 欧拉函数之HDU2588 GCD
- hdu2588 GCD(欧拉函数)
- hdu2588 GCD 给定n,m。求x属于[1,n]。有多少个x满足gcd(x,n)>=m; 容斥或者欧拉函数
- Hdu2588 GCD 欧拉函数
- hdu2588gcd-欧拉函数应用
- [HDU2588]GCD 欧拉函数
- hdu2588 gcd 欧拉函数
- HDU2588 GCD 欧拉函数简单应用
- HDU2588_大区间_GCD_欧拉函数应用
- HDU2588GCD(欧拉函数)
- HDU2588--GCD(欧拉函数)
- hdu2588 GCD (欧拉函数)
- HDU2588:GCD(欧拉函数的应用)
- hdu2588 GCD(欧拉函数)
- HDU2588 GCD(欧拉函数)
- hdu2588 GCD (欧拉函数)
- hdu 2588 GCD-欧拉函数
- GCD HDU - 2588(欧拉函数)
- hdu - 2588 - GCD(欧拉函数求同值gcd个数)
- HDU 1695 GCD 【容斥】【质因数分解】【欧拉函数】