数学问题 欧拉函数 GCD

先算第一象限能看到的树,答案乘以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 }