hdu3501 Calculation 2(欧拉函数)

来源:互联网 发布:淘宝女装店铺设计图 编辑:程序博客网 时间:2024/05/18 11:28


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;}


0 0
原创粉丝点击