您的位置:首页 > 其它

GCD - Extreme (II) (数论,欧拉函数)

2017-05-09 14:42 363 查看
题目来源https://vjudge.net/problem/UVA-11426

【题意】

求在1-n之间所有任意两个数的的最大公因数的和。

【思路】

做完这道题,依旧感觉头脑懵懵的,看了好多篇博客方才看懂了这道题的解法,因为之前做过几道数论题,关于素数的比较多,这到题因为最大公因数就自然而然的想到了素数筛法,一直在找所谓的规律。最后终于崩溃了。。。

便搜了博客慰藉我不安的心灵,但是很多博客我发现一个共同的优点,写的让我看不懂,这就比较厉害了。终于,被我发现了一篇特别接地气的博文,此处为链接:http://www.cnblogs.com/staginner/archive/2012/10/29/2745135.html,然后接下来,就是我的叙述和理解。

因为让求的1-n区间里任两个数的最大公因数之和,所以假设gcd(n,m)=z,在这里,因为n和m的范围都是超级大,所以,不能枚举n,m,但是可以枚举m,z,或者n,z。

具体思路是:假设gcd(x,y)=1,那么当执行到x,y的时候,最后的和都要加1,那么相应的,执行到2x,2y时,最后的和都要加2,以此类推,执行到kx,ky的时候最后的和都要加k,那么这些一切的根源都归咎于gcd(x,y)=1,所以才有了上面那一句话,枚举n,z(n,m选其一,无所谓的),这里的z就是上面的1,2,。。k。枚举z的问题解决了,那么轮到n了,枚举n,假设一个值为num,那么num代表与n的最大公因数是z(1,2,3,,,,k)的个数,这里的z有好多值,但是任何的z(大于1)都可以有最根本的gcd(x,y)推出,所以算出只需要算出z=1时num的值就可以了,这个时候,就会想到欧拉函数值(小于n的数里与n互质的个数)。然后,这道题算是结束了。

【代码】

#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#define mem(a,b) memset(a,b,sizeof(a))
#define MAXN 4000010
using namespace std;
const int INF=1e9;
typedef long long LL;
const int maxn=4e6+10;
LL euler[maxn];
LL a[maxn];
int main()
{
LL n;
mem(euler,0);
euler[1]=1;
for(int i=2; i<=maxn; i++)
{
if(!euler[i])//筛法求欧拉函数值
{
euler[i]=i-1;
for(int j=2*i; j<=maxn; j+=i)
{
if(!euler[j])
euler[j]=j;
euler[j]=euler[j]/i*(i-1);
}
}
for(int j=1; i*j<=maxn; j++)//根据gcd(x,y)推出z不等于1的num值。
a[i*j]+=euler[i]*j;
}
for(int i=1; i<=maxn; i++)//累加。成前缀合
a[i]+=a[i-1];
while(~scanf("%lld",&n)&&n)
printf("%lld\n",a
);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: