先算第一象限能看到的树,答案乘以4就是四个象限的数的总数,再加上坐标轴上四棵树,就是总共能看到的树。
树的总数为(2*a+1)*(2*b+1)-1 ←矩形面积除去原点位置
设一棵树的坐标是(x,y),当x,y互质时可以被看到,所以用欧拉函数算即可。
a远比b小,所以先算出1~a的欧拉函数,而区间[1..a],[a+1..2*a]..中的满足条件数都相同,直接乘区间数即可,最后多出来的一小段单独判断gcd
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 const int mxn=2100; 9 int phi[mxn]; 10 int a,b; 11 double ans; 12 int gcd(int a,int b){ 13 if(!b)return a; 14 return gcd(b,a%b); 15 } 16 void euler(){ 17 int i,j; 18 phi[1]=1; 19 for(i=2;i<mxn;i++){ 20 if(!phi[i]){ 21 for(j=i;j<mxn;j+=i){ 22 if(!phi[j])phi[j]=j; 23 phi[j]=phi[j]/i*(i-1); 24 } 25 } 26 } 27 return; 28 } 29 int main(){ 30 euler(); 31 int i,j; 32 while(scanf("%d%d",&a,&b) && a){ 33 long long num=0; 34 for(i=1;i<=a;i++){ 35 num+=(long long)phi[i]*(b/i); 36 for(j=1;j<=b%i;j++){ 37 if(gcd(i,j)==1)num++; 38 } 39 } 40 num=num*4+4;//可以看到的树 41 double all; 42 all=(double)(2*a+1)*(2*b+1)-1; 43 ans=(double)num/(double)all; 44 printf("%.7f\n",ans); 45 } 46 return 0; 47 }