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 <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
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;
}