HDU4279(2012年天津网络赛---数论分析题)

题目:Number


题意: 给出一个f(x),表示不大于x的正整数里,不整除x且跟x有大于1的公约数的数的个数。定义F(x),为不大于x的正整数里,满足f(x)的值为奇数的数的个数。题目就是求这个F(x)。


网上很多方法就是打表找规律,已经谈不上是算法了。

这里我们可以来分析:


 

 

不整除x且跟x有大于1的公约数的数的个数 f(x)=x-约数个数-互质数个数+1 。


把x素因子分解,易知x的约数个数为(质数的幂+1)的累乘。所以若要使约数为奇数,充要条件是(质数的幂+1)都为奇

 

数,即质数的幂都为偶数。所以此时x必然是一个平方数。


综上,x为平方数,其约数个数为奇数;x为非平方数,其约数个数为偶数。


互质数个数,我们有欧拉函数。

 

这里用到一个结论:欧拉函数在n>2时,值都为偶数。

 

 

 

所以,

当x>2时:

若x为平方数,f(x)=x-奇-偶+1,要使f(x)为奇数,则x必为奇数;

若x为非平方数,f(x)=x-偶-偶+1,要使f(x)为奇数,则x必为偶数。 

当x=1或2时,f(x)=0.


综上,F(x)的值为[3,x]中,奇数平方数+偶数非平方数的个数和,即 偶数个数-偶数^2的个数+奇数^2的个数。

而偶数个数为 x/2-1,-1是为了把2减掉。偶数^2个数为 sqrt(x)/2,奇数^2个数为 ( sqrt(x)-(sqrt(x)/2) )-1,这里-1是为了把1减掉。


所以,化简后,F(x)=x/2-1+(sqrt(x)%2? 0:-1).


 

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>

using namespace std;
typedef long long LL;

LL Solve(LL n)
{
    LL ans=0;
    if(n<6) return 0;
    ans+=n/2-2;
    if((LL)sqrt(1.0*n)&1) ans++;
    return ans;
}

int main()
{
    LL a,b,t;
    cin>>t;
    while(t--)
    {
        cin>>a>>b;
        cout<<Solve(b)-Solve(a-1)<<endl;
    }
    return 0;
}


 


posted @ 2013-08-03 22:31  javawebsoa  Views(230)  Comments(0Edit  收藏  举报