hdu1299 Diophantus of Alexandria---素因子分解

来源:互联网 发布:编程逻辑思维训练500题 编辑:程序博客网 时间:2024/06/05 11:35

Diophantus of Alexandria

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1849 Accepted Submission(s): 698

Problem Description
Diophantus of Alexandria was an egypt mathematician living in Alexandria. He was one of the first mathematicians to study equations where variables were restricted to integral values. In honor of him, these equations are commonly called diophantine equations. One of the most famous diophantine equation is x^n + y^n = z^n. Fermat suggested that for n > 2, there are no solutions with positive integral values for x, y and z. A proof of this theorem (called Fermat’s last theorem) was found only recently by Andrew Wiles.

Consider the following diophantine equation:

1 / x + 1 / y = 1 / n where x, y, n ∈ N+ (1)

Diophantus is interested in the following question: for a given n, how many distinct solutions (i. e., solutions satisfying x ≤ y) does equation (1) have? For example, for n = 4, there are exactly three distinct solutions:

1 / 5 + 1 / 20 = 1 / 4
1 / 6 + 1 / 12 = 1 / 4
1 / 8 + 1 / 8 = 1 / 4

Clearly, enumerating these solutions can become tedious for bigger values of n. Can you help Diophantus compute the number of distinct solutions for big values of n quickly?

Input
The first line contains the number of scenarios. Each scenario consists of one line containing a single number n (1 ≤ n ≤ 10^9).

Output
The output for every scenario begins with a line containing “Scenario #i:”, where i is the number of the scenario starting at 1. Next, print a single line with the number of distinct solutions of equation (1) for the given value of n. Terminate each scenario with a blank line.

Sample Input
2
4
1260

Sample Output
Scenario #1:
3

Scenario #2:
113

令y=n+k,那么x=n*n/k+n,也就是问我们到底能有多少种K使之整除,换句话说就是求n*n的因子数目,我们知道根据数分解定理可得任何一个数都可以写成a1^x1*a2^x2*a3^x3………,其中的a1,a2,a3.。。。。都是素数,而n的因子数目就是(1+x1)(1+x2)(1+x3),而我们是n*n,所以我们就是(1+2*x1)(1+2*x2)(1+2*x3)*,等等,唉我们这样就可以求出来了吗,不是的,我们要进行素数打表时有一个问题需要注意,那就是我们需要求出的素数范围不能是10e,否则就tle了!!!!!!!那应该是多少呢??是sqrt(n),当然了会有人问我如果因子中有数超过了这个呢???就算超过了,也就只有一个会抄过,所以如果最后剩下的那个不是1,那就是大素数了,而它的数目又只是1,所以是(1+2*1)=3;应该乘以三,还有我们算的时候x与y交换只能算一种,要除以2,但是n也是因子之一啊,我们必须加上它做成两个它,再除以二就是了!!!!

定理1: 一个正整数 n 可以用素因子唯一表示为 p1^r1 * p2^r2 * … pk^rk (其中 pi 为素数) , 那么这个数的因子的个数就是,(r1+1)*(r2+1)~(rk+1).

定理2:如果一个数字 n = p1^r1 * p2^r2 * … pk^rk ,那么 n*n = p1^r1 * p2^r2 * … pk^rk * p1^r1 * p2^r2 * … pk^rk ,它的因子的个数就是 (2*r1+1)*(2*r2+1)~(2*rk+1).

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 1e7+10;typedef long long LL;int p[maxn/10],cnt;bool vis[maxn];int fac[1000],tot;void init(){    cnt=0;    memset(vis,0,sizeof(vis));    for(int i=2;i<maxn;i++){        if(!vis[i]){            p[cnt++]=i;            for(int j=i+i;j<maxn;j+=i) vis[j]=1;        }    }}LL get(LL x){    tot=0;    memset(fac,0,sizeof(fac));    for(int i=0;i<cnt&&p[i]*p[i]<=x;i++){        if(x%p[i]==0){            while(x%p[i]==0) fac[tot]++,x/=p[i];            tot++;        }    }    if(x>1) fac[tot++]=1;    LL ans = 1;    for(int i=0;i<tot;i++) ans=ans*(2*fac[i]+1);    return ans ;}int main(){    init();    int t,cas=1;    scanf("%d",&t);    while(t--){        LL n;        scanf("%I64d",&n);        printf("Scenario #%d:\n%I64d\n\n",cas++,(get(n)+1)/2);    }    return 0;}
0 0
原创粉丝点击