题目链接
#1284 : 机会渺茫
时间限制: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<=10^6
对于100%的数据,满足1<=N,M<=10^12
输出
对于每组测试数据,输出两个互质的正整数A和B(以A分之B表示小Hi能够追到小Z的几率)。
- 样例输入
-
3 2
- 样例输出
-
4 1
分析:对 n 和 m 分解,得到n和m的每一个素数的指数en[],em[],然后取公约数,即取每个指数小的那个得到新的 et[], sum(et[]) / sum(en[]) * sum(em[])即所求,就是在en里面找一个,在em里面找一个,1/(sum[en] * sum[em]),一共有sum[et]个
题目等级为2,然后我却WA了好几次,RE了好几次 =_=...1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 typedef long long LL; 6 const int Max = 10000000 + 5; //开到6次RE 7 bool flag[Max + 5]; 8 int prime[Max + 5], tot; 9 int en[Max + 5], em[Max + 5], et[Max + 5]; 10 void get_prime() 11 { 12 memset(flag, false, sizeof(flag)); 13 tot = 0; 14 for (int i = 2; i <= Max;i ++) 15 { 16 if (!flag[i]) 17 { 18 prime[++tot] = i; 19 for (int j = i; j <= Max / i; j++) 20 flag[i * j] = true; 21 } 22 } 23 } 24 void get_fact(LL n, int * temp) 25 { 26 memset(temp, 0, sizeof(temp)); 27 for (int i = 1; i <= tot; i++) 28 { 29 if (prime[i] > n) 30 break; 31 if (n % prime[i] == 0) 32 { 33 while (n % prime[i] == 0) 34 { 35 n = n / prime[i]; 36 temp[prime[i]]++; 37 } 38 } 39 } 40 if (n > 1) 41 temp[n]++; 42 } 43 LL get_sum(int temp[]) 44 { 45 LL sum = 1; 46 for (int i = 1; i <= tot; i++) 47 { 48 if (temp[prime[i]]) 49 sum *= (temp[prime[i]] + 1); 50 } 51 return sum; 52 } 53 void solve() 54 { 55 memset(et, 0, sizeof(et)); 56 for (int i = 1; i <= tot; i++) 57 { 58 if (en[prime[i]] && em[prime[i]]) 59 { 60 int minn = min (en[prime[i]], em[prime[i]]); //取最小的指数 61 et[prime[i]] += minn; 62 } 63 } 64 } 65 LL get_gcd(LL a, LL b) 66 { 67 if (b == 0) 68 return a; 69 return get_gcd(b, a % b); 70 } 71 int main() 72 { 73 get_prime(); 74 LL n, m; 75 scanf("%lld%lld", &n, &m); 76 get_fact(n, en); 77 get_fact(m, em); 78 solve(); 79 LL numn = get_sum(en); 80 LL numm = get_sum(em); 81 LL numf = get_sum(et); 82 83 // 最后结果就是 numf / (numn * numm) 84 所以先对numf 和 numn约分, 85 然后把约分后的numf与numm约分,最后numn * numm 86 LL x1 = numf; 87 LL t1 = get_gcd(numn, numf); 88 x1 = x1 / t1; 89 numn = numn / t1; 90 91 LL t2 = get_gcd(numm, x1); 92 x1 = x1 / t2; 93 numm = numm / t2; 94 numn = numn * numm; 95 96 printf("%lld %lld ", numn, x1); 97 return 0; 98 }