hiho一下 第144周(机会渺茫)解题报告及拓展

题目1 : 机会渺茫

时间限制:5000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi最近在追求一名学数学的女生小Z。小Z其实是想拒绝他的,但是找不到好的说辞,于是提出了这样的要求:对于给定的两个正整数N和M,小Hi随机选取一个N的约数N',小Z随机选取一个M的约数M',如果N'和M'相等,她就答应小Hi。

小Z让小Hi去编写这个随机程序,到时候她review过没有问题了就可以抽签了。但是小Hi写着写着,却越来越觉得机会渺茫。那么问题来了,小Hi能够追到小Z的几率是多少呢?

输入

每个输入文件仅包含单组测试数据。

每组测试数据的第一行为两个正整数N和M,意义如前文所述。

对于40%的数据,满足1<=N,M<=106

对于100%的数据,满足1<=N,M<=1012

输出

对于每组测试数据,输出两个互质的正整数A和B(以A分之B表示小Hi能够追到小Z的几率)。

样例输入
3 2
样例输出
4 1

 

Solution:

 

Way1:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <stdbool.h>
  4 
  5 long ans=0,maxn,zhi[100000];
  6 
  7 void Get_Zhi()
  8 {
  9     long i,j;
 10     bool vis[maxn+1];
 11     for (i=2;i<=maxn;i++)
 12         vis[i]=true;
 13     for (i=2;i<=maxn;i++)
 14     {
 15         if (vis[i])
 16         {
 17             ans++;
 18             zhi[ans]=i;
 19         }
 20         for (j=1;j<=ans;j++)
 21         {
 22             if (i*zhi[j]>maxn)
 23                 break;
 24             vis[i*zhi[j]]=false;
 25             if (i%zhi[j]==0)
 26                 break;
 27         }
 28     }
 29 }
 30 
 31 int main()
 32 {
 33     long long n,m,a,b,temp,x,y;
 34     long i,g;
 35     scanf("%lld%lld",&n,&m);
 36     if (n>m)
 37         maxn=(long)sqrt(n);
 38     else
 39         maxn=(long)sqrt(m);
 40     Get_Zhi();
 41     if (n>m)
 42     {
 43         a=n;
 44         b=m;
 45     }
 46     else
 47     {
 48         a=m;
 49         b=n;
 50     }
 51     while (b)
 52     {
 53         temp=b;
 54         b=a%b;
 55         a=temp;
 56     }
 57     x=1;
 58     y=1;
 59     //a
 60     if (a!=1)
 61     {
 62         for (i=1;i<=ans;i++)
 63             if (a%zhi[i]==0)
 64             {
 65                 g=1;
 66                 while (a%zhi[i]==0)
 67                 {
 68                     a/=zhi[i];
 69                     g++;
 70                 }
 71                 x*=g;
 72                 if (a==1)
 73                     break;
 74             }
 75         //a,n,m都有该质数,且系数都为1(若系数大于1,则相乘大于最大值)
 76         if (a!=1)
 77         {
 78             //x*2,y*4->x,y*2
 79             y*=2;
 80             n/=a;
 81             m/=a;
 82         }
 83     }
 84 
 85     //n
 86     if (n!=1)
 87     {
 88         for (i=1;i<=ans;i++)
 89             if (n%zhi[i]==0)
 90             {
 91                 g=1;
 92                 while (n%zhi[i]==0)
 93                 {
 94                     n/=zhi[i];
 95                     g++;
 96                 }
 97                 y*=g;
 98                 if (n==1)
 99                     break;
100             }
101         if (n!=1)
102             y*=2;
103     }
104 
105     //m
106     if (m!=1)
107     {
108         for (i=1;i<=ans;i++)
109             if (m%zhi[i]==0)
110             {
111                 g=1;
112                 while (m%zhi[i]==0)
113                 {
114                     m/=zhi[i];
115                     g++;
116                 }
117                 y*=g;
118                 if (m==1)
119                     break;
120             }
121         if (m!=1)
122             y*=2;
123     }
124 
125     a=y;
126     b=x;
127     while (b)
128     {
129         temp=b;
130         b=a%b;
131         a=temp;
132     }
133     x/=a;
134     y/=a;
135     printf("%lld %lld\n",y,x);
136     return 0;
137 }

 

Way2:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <stdbool.h>
  4 
  5 long ans=0,maxn,zhi[100000];
  6 
  7 //打质数表!
  8 
  9 void Get_Zhi()
 10 {
 11     long i,j;
 12     bool vis[maxn+1];
 13     for (i=2;i<=maxn;i++)
 14         vis[i]=true;
 15     for (i=2;i<=maxn;i++)
 16     {
 17         if (vis[i])
 18         {
 19             ans++;
 20             zhi[ans]=i;
 21         }
 22         for (j=1;j<=ans;j++)
 23         {
 24             if (i*zhi[j]>maxn)
 25                 break;
 26             vis[i*zhi[j]]=false;
 27             if (i%zhi[j]==0)
 28                 break;
 29         }
 30     }
 31 }
 32 
 33 int main()
 34 {
 35     long long n,m,y=1;
 36     long i,j,g1=0,g2=0,p[100],q[100],u[100],v[100];
 37     scanf("%lld%lld",&n,&m);
 38     if (n>m)
 39         maxn=(long)sqrt(n);
 40     else
 41         maxn=(long)sqrt(m);
 42     Get_Zhi();
 43 
 44     //n
 45     if (n!=1)
 46     {
 47         for (i=1;i<=ans;i++)
 48             if (n%zhi[i]==0)
 49             {
 50                 g1++;
 51                 p[g1]=i;
 52                 q[g1]=1;
 53                 while (n%zhi[i]==0)
 54                 {
 55                     n=n/zhi[i];
 56                     q[g1]++;
 57                 }
 58                 if (n==1)
 59                     break;
 60             }
 61     }
 62     if (n!=1)
 63         y*=2;
 64 
 65     //m
 66     if (m!=1)
 67     {
 68         for (i=1;i<=ans;i++)
 69             if (m%zhi[i]==0)
 70             {
 71                 g2++;
 72                 u[g2]=i;
 73                 v[g2]=1;
 74                 while (m%zhi[i]==0)
 75                 {
 76                     m/=zhi[i];
 77                     v[g2]++;
 78                 }
 79                 if (m==1)
 80                     break;
 81             }
 82     }
 83     if (m!=1 && m!=n)
 84         y*=2;
 85     i=1;
 86     j=1;
 87     while (i<=g1 && j<=g2)
 88     {
 89         if (p[i]<u[j])
 90         {
 91             y*=q[i];
 92             i++;
 93         }
 94         else if (u[j]<p[i])
 95         {
 96             y*=v[j];
 97             j++;
 98         }
 99         else
100         {
101             if (q[i]>v[j])
102                 y*=q[i];
103             else
104                 y*=v[j];
105             i++;
106             j++;
107         }
108     }
109     while (i<=g1)
110     {
111         y*=q[i];
112         i++;
113     }
114     while (j<=g2)
115     {
116         y*=v[j];
117         j++;
118     }
119     printf("%lld 1\n",y);
120     return 0;
121 }

 

Way3:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <stdbool.h>
  4 
  5 long ans=0,maxn,zhi[100000];
  6 
  7 void Get_Zhi()
  8 {
  9     long i,j;
 10     bool vis[maxn+1];
 11     for (i=1;i<=maxn;i++)
 12         vis[i]=true;
 13     for (i=2;i<=maxn;i++)
 14     {
 15         if (vis[i])
 16         {
 17             ans++;
 18             zhi[ans]=i;
 19         }
 20         for (j=1;j<=ans;j++)
 21         {
 22             if (i*zhi[j]>maxn)
 23                 break;
 24             vis[i*zhi[j]]=false;
 25             if (i%zhi[j]==0)
 26                 break;
 27         }
 28     }
 29 }
 30 
 31 int main()
 32 {
 33     long long n,m,a,b,temp,x,y;
 34     long g,i,r=0,t,p[100],q[100];
 35     scanf("%lld%lld",&n,&m);
 36     if (n>m)
 37         maxn=(long)sqrt(n);
 38     else
 39         maxn=(long)sqrt(m);
 40     Get_Zhi();
 41     if (n>m)
 42     {
 43         a=n;
 44         b=m;
 45     }
 46     else
 47     {
 48         a=m;
 49         b=n;
 50     }
 51     while (b)
 52     {
 53         temp=b;
 54         b=a%b;
 55         a=temp;
 56     }
 57     x=1;
 58     y=1;
 59 
 60     n/=a;
 61     m/=a;
 62 
 63     //a
 64     r=0;
 65     if (a!=1)
 66     {
 67     for (i=1;i<=ans;i++)
 68         if (a%zhi[i]==0)
 69         {
 70             r++;
 71             p[r]=i;
 72             q[r]=1;
 73             while (a%zhi[i]==0)
 74             {
 75                 a/=zhi[i];
 76                 q[r]++;
 77             }
 78             x*=q[r];
 79             if (a==1)
 80                 break;
 81         }
 82         //a,n,m都有该质数,且系数都为1(若系数大于1,则相乘大于最大值)
 83         //x*2,y*4->x,y*2
 84         if (a!=1)
 85             y*=2;
 86     }
 87     p[r+1]=1000000;
 88 
 89     //n
 90     if (n!=1)
 91     {
 92         t=1;
 93         for (i=1;i<=ans;i++)
 94             if (n%zhi[i]==0)
 95             {
 96                 g=1;
 97                 while (n%zhi[i]==0)
 98                 {
 99                     n/=zhi[i];
100                     g++;
101                 }
102                 //p[r+1]=1000000;
103                 while (p[t]<i)
104                 {
105                     y*=q[t];
106                     t++;
107                 }
108                 if (p[t]==i)
109                 {
110                     y*=(g+q[t]-1);
111                     t++;
112                 }
113                 else
114                     y*=g;
115                 if (n==1)
116                     break;
117             }
118         if (n!=1)
119             y*=2;
120         while (t<=r)
121         {
122             y*=q[t];
123             t++;
124         }
125     }
126     else
127         y*=x;
128 
129     //m
130     if (m!=1)
131     {
132         t=1;
133         for (i=1;i<=ans;i++)
134             if (m%zhi[i]==0)
135             {
136                 g=1;
137                 while (m%zhi[i]==0)
138                 {
139                     m/=zhi[i];
140                     g++;
141                 }
142                 //p[r+1]=1000000;
143                 while (p[t]<i)
144                 {
145                     y*=q[t];
146                     t++;
147                 }
148                 if (p[t]==i)
149                 {
150                     y*=(g+q[t]-1);
151                     t++;
152                 }
153                 else
154                     y*=g;
155                 if (m==1)
156                     break;
157             }
158         if (m!=1)
159             y*=2;
160         while (t<=r)
161         {
162             y*=q[t];
163             t++;
164         }
165     }
166     else
167         y*=x;
168 
169     a=y;
170     b=x;
171     while (b)
172     {
173         temp=b;
174         b=a%b;
175         a=temp;
176     }
177     x/=a;
178     y/=a;
179     printf("%lld %lld\n",y,x);
180     return 0;
181 }
182 /*
183 input:
184 16 8
185 output:
186 5 1
187 
188 input:
189 60 48
190 output:
191 20 1
192 */

Advance:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 #define maxn 100000
 5 #define maxs 100000
 6 
 7 long zhi[maxn],z[maxs+1][12],g[maxs+1][12],ansz[maxs+1];
 8 
 9 void Get_Zhi()
10 {
11     long i,j,s,ans=0;
12     long long k;
13     bool vis[maxn+1];
14     for (i=2;i<=maxn;i++)
15         vis[i]=true;
16     for (i=2;i<=maxn;i++)
17     {
18         if (vis[i])
19         {
20             ans++;
21             zhi[ans]=i;
22             for (j=i;j<=maxs;j+=i)
23             {
24                 ansz[j]++;
25                 z[j][ansz[j]]=i;
26                 //为了求约数总数,比正确个数多1
27                 g[j][ansz[j]]=2;
28             }
29             k=(long long)i*i;
30             s=2;
31             while (k<=maxs)
32             {
33                 for (j=k;j<=maxs;j+=k)
34                     g[j][ansz[j]]++;
35                 k=(long long)k*i;
36                 s++;
37             }
38         }
39         for (j=1;j<=ans;j++)
40         {
41             if (i*zhi[j]>maxn)
42                 break;
43             vis[i*zhi[j]]=false;
44             if (i%zhi[j]==0)
45                 break;
46         }
47     }
48 }
49 
50 int main()
51 {
52     long i,j,m,n;
53     double result=0,re;
54     for (i=1;i<=maxs;i++)
55         ansz[i]=0;
56     Get_Zhi();
57     for (n=1;n<=maxs;n++)
58         for (m=1;m<=maxs;m++)
59         {
60             re=1.0;
61             i=1;
62             j=1;
63             while (i<=ansz[n] && j<=ansz[m])
64             {
65                 if (z[n][i]<z[m][j])
66                 {
67                     re/=g[n][i];
68                     i++;
69                 }
70                 else if (z[n][i]>z[m][j])
71                 {
72                     re/=g[m][j];
73                     j++;
74                 }
75                 else
76                 {
77                     if (g[n][i]>g[m][j])
78                         re/=g[n][i];
79                     else
80                         re/=g[m][j];
81                     i++;
82                     j++;
83                 }
84             }
85             while (i<=ansz[n])
86             {
87                 re/=g[n][i];
88                 i++;
89             }
90             while (j<=ansz[m])
91             {
92                 re/=g[m][j];
93                 j++;
94             }
95             result+=re;
96         }
97     printf("%lf\n",result*1.0/maxs/maxs);
98     return 0;
99 }

 

 

posted @ 2017-04-08 21:47  congmingyige  阅读(283)  评论(0编辑  收藏  举报