hdoj 1299 Diophantus of Alexandria

hdoj 1299 Diophantus of Alexandria

链接http://acm.hdu.edu.cn/showproblem.php?pid=1299

题意:求 1/x + 1/y = 1/n (x <= y) 的组数。

思路:转化为一个数的因子个数。

因为x,y,z 都是整数,令 y = n+k (倒数和相等,x,y 明显大于 n),带入式子可得 x = n*n / k + n ;所以 x 的组数就与k相关了,只要 k 满足是 n*n 的约数,组数就 +1。假设 n = (p1^r1) * (p2^r2) * (p3^r3) * ... * (pn^rn),则 n 的约数个数为 (r1+1) * (r2+1) * ... * (rn+1),   n * n 可分解为 n * n = (p1^2r1) * (p2^2r2) * … *(pn^2rn), 所以 n*n 的约数个数为 cnt = (2r1+1) * (2r2+1) * … * (2rn+1)。公式中的 p1,p2,……,pn 为素数。所以就转化为求素数的问题,这里用到线性筛法求 sqrt(n)内的素数。因为 x < y, 所以把结果除以2就得到答案。

代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<cstdio>
 5 using namespace std;
 6 
 7 typedef long int LL;
 8 const int maxv = 35000;
 9 int prime[4000], num[maxv];
10 
11 void prim()    //筛法求素数
12 {
13     int i, j, k = 1;
14     for(i = 2; i < maxv; ++i)    num[i] = 1;
15     prime[0] = 2, num[4] = 0;
16     for(i = 3; i < maxv; i += 2)
17     {
18         if(num[i])    prime[k++] = i;
19         for(j = 0; (j<k && i*prime[j] < maxv); ++j)
20         {
21             num[i*prime[j]] = 0;
22             if(i%prime[j] == 0)    break;
23         }
24     }
25 }
26 
27 int counter(int n)    //计算约数个数
28 {
29     int cnt = 1, i, j, k = 0;
30     int q;
31     i = (int)sqrt(n*1.0)+1;
32     for(j = 0; prime[j] <= i; ++j)
33     {
34         if(n % prime[j] == 0)
35         {
36             q = 0;
37             while(n%prime[j] == 0){
38                 n = n/prime[j], q++;
39             }
40             cnt *= (2*q+1);
41         }
42     }
43 
44     if(n > 1)
45         cnt *= 3;
46     return (cnt+1)/2;
47 }
48 int main()
49 {
50     int n;
51     int i = 1, cnt, t;
52     prim();
53     //freopen("hdoj1299.txt", "r", stdin);
54     cin >> t;
55     while(t--)
56     {
57         cin >> n;
58         cnt = counter(n);
59         cout<<"Scenario #" << i++ <<":\n" << cnt << endl << endl;
60     }
61     return 0;
62 }

 

转载于:https://www.cnblogs.com/Duahanlang/p/3204202.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值