您的位置:首页 > 其它

hdu3501 Calculation 2(欧拉函数)

2016-11-22 08:57 169 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3501

题意:求小于n中与n不互为质数的正整数之和。

思路:主要就是欧拉函数的入门。看这个吧:欧拉入门

欧拉函数是为了求小于或等于n的数中与n互质的数的数目。

直接不分所以然就给了个这样的公式:φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…..(1-1/pn),φ(n)是欧拉函数的值,p1、p2...是素因子的大小。欧拉函数中是每算一个素因子然后乘一项式子。比如说先算n*(1-1/p1),然后算出的ans再乘以(1-1/p2),考虑到省略掉乘法可以降低时间所以把ans乘进去写成了减法;

接着就是完全消除素因子,比如8的素因子2,必须除多次才可完全消除;

最后是未消除素因子的处理,由于上面消因子的时候实际上是改变了n的值,使得原本可以满足判断条件的素因子因为n过小而漏掉,这一步就是为此而存在。不过这个因子不会太大,若是太大就不会被漏掉,所以不必多次消除,一次就可以达到目的。

欧拉函数的扩展:小于或等于n中与n互质的数的和为euler(n)*n/2;

本题中是求与其不互质的数的和。

#include <stdio.h>
#include <algorithm>

using namespace std;

typedef long long ll;

ll euler(ll n)
{
ll 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 main()
{
// freopen("in.txt", "r", stdin);
ll n, ans;
while(~scanf("%lld", &n))
{
if(n == 0) break;
ans = n*(n+1)/2-n;
ans -= euler(n)*n/2;
printf("%lld\n", ans%1000000007);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu