hdu

来源:互联网 发布:绥化学院教务管理网络 编辑:程序博客网 时间:2024/05/17 23:22

Given a positive integer N, your task is to calculate the sum of the positive integers less than N which are not coprime to N. A is said to be coprime to B if A, B share no common positive divisors except 1.
Input
For each test case, there is a line containing a positive integer N(1 ≤ N ≤ 1000000000). A line containing a single 0 follows the last test case.
Output
For each test case, you should print the sum module 1000000007 in a line.
Sample Input
340
Sample Output
02

题目给出n,让求小于n且不与n互质的数的和

首先欧拉函数Euler(n)是求小于n且与n互质的数的个数,再有gcd的性质:如果gcd(n,i)=1,则gcd(n,n-i)=1

那么,可以看做在[1,n-1]中与n互质的数是成对出现的,即如果i与n互质,则(n-i)也与n互质(Euler(n)为偶数)。而且可以发现这对数(i与n-i)的和为n。

进一步得到结论:小于n且与n互质的数的和为n*Euler(n)/2;

那么对于此题课先求1~n的和,再减去n*Euler(n)/2

代码:

#include<iostream>#include<string>#include<cstdio>#include<algorithm>#include<cmath>#include<iomanip>#include<queue>#include<cstring>#include<map>using namespace std;typedef long long ll;#define mod 1000000007ll n;ll euler_phi(ll n){    ll m=(ll)sqrt(n+0.5);    ll ans=n;    for(ll i=2;i<=m;i++)    {        if(n%i==0)        {            ans=ans/i*(i-1);            while(n%i==0)                n/=i;        }    }    if(n>1)        ans=ans/n*(n-1);    return ans;}int main(){    while(scanf("%lld",&n)!=EOF)    {        if(n==0)            break;        ll ans=(n*(n-1)/2)%mod;  //求1~n的和        ans=(ans-(n*euler_phi(n)/2)%mod+mod)%mod;        printf("%lld\n",ans);    }    return 0;}


在做这个题的同时发现上面代码200多ms,而有人只有15ms,那么我认为一定是欧拉函数不同造成

于是同下面欧拉函数时间为15 ms

ll euler_phi(ll n){    ll ans=n;    for(ll 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;}

用下面欧拉函数为171ms

ll euler_phi(ll n){    ll ans=n;    ll m=(ll)sqrt(n+0.5);    for(ll i=2;i<=m;i++)    {        if(n%i==0)        {            ans-=ans/i;            while(n%i==0)                n/=i;        }    }    if(n>1)        ans-=ans/n;;    return  ans;}
下面280ms

ll euler_phi(ll n){    ll ans=n;    ll m=(ll)sqrt(n+0.5);    for(ll i=2;i<=m;i++)    if(n%i==0)    {        ans-=ans/i;        while(n%i==0)            n/=i;    }    if(n>1)        ans-=ans/n;;    return  ans;}


其中缘由我不清楚,但还是用快的吧

原创粉丝点击