hdu4279-欧拉函数+约数个数+打表+sqrt()精度问题

http://acm.hust.edu.cn/vjudge/problem/31861/origin

题目要求 对一个数n, 从【1,n】里去掉其约数,并去掉所有与其互质的数,求剩余数的个数,如果个数为奇数,则 是一个real number

求区间【X,Y】之间的real number数

先是打表发现规律,其实也蛮好证明:

首先 对一个数,与其互质的数肯定是偶数个的(根据欧拉公式可得),其次对于约数,只有平方数的约数才是奇数,其余都是偶数,

如果该数不是平方数

num = n-euler(n)-divisor(n)+1,即偶数的非平方数都是real number ,加1是因为1即使互质也是因子

如果是平方数,则只有奇数的平方数是real number


则如果要求【1,x】有多少个real number ,先求多少个偶数,再减去偶数平方数加奇数平方数

偶数就是n/2, 奇数平方数和偶数平方数,如果sqrt(n)%2,则奇数多一个,否则一样

注意sqrt(1.0*n)会爆,sqrt((double )n) 会爆,只有sqrt((long long doubel )n),才不会

或者 int x=sqrt(n), if (x*x>n) x--;


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001;

int num[]= {0,0,0,0,0,0,1,1,2,3}; 
long long cal1(long long n)
{
    if(n<=4)
        return 0;
    long long ans=(n-4)/2;

    long long tmp=sqrt(n);
    if(tmp*tmp>n)
        tmp--;
    if(tmp%2)
        ans++;


    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
     long long x,y;
         scanf("%lld%lld",&x,&y);
         long long ret1=cal(x-1);
         long long ret2=cal(y); 
         printf("%lld\n",ret2-ret1); 
    }
    return 0;

}



你可能感兴趣的:(数学,欧拉函数)