求n的因子個數與其因子數之和


方法一:朴素算法:O(n)。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int get_num(int n){
 4     int num=0;
 5     for(int i=1;i<=n;++i)
 6         if(n%i==0)num++;
 7     return num;
 8 }
 9 int get_sum(int n){
10     int tot=0;
11     for(int i=1;i<=n;++i)
12         if(n%i==0)tot+=i;
13     return tot;
14 }
15 int main(){
16     int n;
17     while(cin>>n){
18         cout<<get_num(n)<<endl;//求n的因子個數
19         cout<<get_sum(n)<<endl;//求n的因子數之和
20     }
21     return 0;
22 }

方法二:約數個數定理:O(√n)。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int get_num(int n){
 4     int tot=1;
 5     for(int i=2;i*i<=n;++i){
 6         if(n%i==0){
 7             int x=0;
 8             while(n%i==0){
 9                 n/=i;
10                 x++;
11             }
12             tot*=(x+1);
13         }
14     }
15     if(n>1)tot*=2;
16     return tot;
17 }
18 int get_sum(int n){
19     int tot=1;
20     for(int i=2;i*i<=n;i++){
21         if(n%i==0){
22             int mul=1;
23             while(n%i==0){
24                 n/=i;
25                 mul*=i;
26             }
27             tot*=(mul*i-1)/(i-1);
28         }
29     }
30     if(n>1)tot*=(n+1);
31     return tot;
32 }
33 int main(){
34     int n;
35     while(cin>>n){
36         cout<<get_num(n)<<endl;//求n的因子個數 37         cout<<get_sum(n)<<endl;//求n的因子數之和 38     }
39     return 0;
40 }

實戰例題:

題解報告:hdu 2521 反素數

Problem Description

反素數就是滿足對於任意i(0<i<x),都有g(i)<g(x),(g(x)是x的因子個數),則x為一個反素數。現在給你一個整數區間[a,b],請你求出該區間的x使g(x)最大。

Input

第一行輸入n,接下來n行測試數據
輸入包括a,b, 1<=a<=b<=5000,表示閉區間[a,b].

Output

輸出為一個整數,為該區間因子最多的數.如果滿足條件有多個,則輸出其中最小的數.

Sample Input

3 2 3 1 10 47 359

Sample Output

2 6 240
Hint
2的因子為:1 2
10的因子為:1 2 5 10
解題思路:求區間[a,b]中最小的元素x,使得所含的因子個數最大,由於數據比較小,暴力枚舉區間[a,b]並套一下公式即可。時間復雜度為O($n\sqrt{n}$)。
AC代碼(15ms):
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,a,b,maxnum,maxindex;
 4 int get_num(int n){//求n的因子個數  5     int tot=1;
 6     for(int i=2;i*i<=n;++i){
 7         if(n%i==0){
 8             int x=0;
 9             while(n%i==0){
10                 n/=i;
11                 x++;
12             }
13             tot*=(x+1);
14         }
15     }
16     if(n>1)tot*=2;
17     return tot;
18 }
19 int main(){
20     while(cin>>n){
21         while(n--){
22             cin>>a>>b;maxnum=0;maxindex=a;
23             for(int i=a;i<=b;++i){
24                 int tmp=get_num(i);
25                 if(tmp>maxnum){maxindex=i;maxnum=tmp;}
26             }
27             cout<<maxindex<<endl;
28         }
29     }
30     return 0;
31 }

 題解報告:hdu 1215 七夕節

Problem Description

七夕節那天,月老來到數字王國,他在城門上貼了一張告示,並且和數字王國的人們說:"你們想知道你們的另一半是誰嗎?那就按照告示上的方法去找吧!"
人們紛紛來到告示前,都想知道誰才是自己的另一半.告示如下:
數字N的因子就是所有比N小又能被N整除的所有正整數,如12的因子有1,2,3,4,6.
你想知道你的另一半嗎?

Input

輸入數據的第一行是一個數字T(1<=T<=500000),它表明測試數據的組數.然后是T組測試數據,每組測試數據只有一個數字N(1<=N<=500000).

Output

對於每組測試數據,請輸出一個代表輸入數據N的另一半的編號.

Sample Input

3
2
10
20

Sample Output

1
8
22
解題思路:求n的因子數之和,簡單套一下公式,時間復雜度為O($t\sqrt{n}$),最壞大概為3e8。
AC代碼一(93ms):
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int t,n;
 4 int get_sum(int n){
 5     int tot=1;
 6     for(int i=2;i*i<=n;++i){
 7         if(n%i==0){
 8             int mul=1;
 9             while(n%i==0){
10                 n/=i;
11                 mul*=i;
12             }
13             tot*=(mul*i-1)/(i-1);
14         }
15     }
16     if(n>1)tot*=(n+1);
17     return tot;
18 }
19 int main(){
20     while(~scanf("%d",&t)){
21         while(t--){
22             scanf("%d",&n);
23             printf("%d\n",get_sum(n)-n);
24         }
25     }
26     return 0;
27 }

AC代碼二(109ms):簡單打表,時間復雜度為nlogn。

 1 #include<bits/stdc++.h>
 2 const int maxn=500005;
 3 using namespace std;
 4 int t,n,sum[maxn];
 5 int main(){
 6     for(int i=1;i<maxn/2;++i)//因子i
 7         for(int j=i*2;j<maxn;j+=i)//j是i的倍數,即j的因子是i
 8             sum[j]+=i;//sum[j]表示其所有因子之和
 9     while(~scanf("%d",&t)){
10         while(t--){
11             scanf("%d",&n);
12             printf("%d\n",sum[n]);
13         }
14     }
15     return 0;
16 }

題解報告:hdu 1999 不可摸數

Problem Description

s(n)是正整數n的真因子之和,即小於n且整除n的因子和.例如s(12)=1+2+3+4+6=16.如果任何數m,s(m)都不等於n,則稱n為不可摸數.

Input

包含多組數據,首先輸入T,表示有T組數據.每組數據1行給出n(2<=n<=1000)是整數。

Output

如果n是不可摸數,輸出yes,否則輸出no

Sample Input

3
2
5
8

Sample Output

yes
yes
no
解題思路:題意就是給一個n(n表示為s(m)的真因子數之和),如果任意數m的真因子之和在n∈[2,1000],那么s(m)就不是不可摸數,否則為不可摸數。打表可以發現數m只需枚舉到10^6便可將真因數之和為1000以內的全部找出來。於是這道題也可以直接打印出89個不可摸數,簡單標記一下即可。
AC代碼一(62ms):
 1 #include<bits/stdc++.h>
 2 const int maxn=1000005;
 3 using namespace std;
 4 int t,n,sum[maxn];bool f[maxn];
 5 int main(){
 6     memset(f,false,sizeof(f));
 7     for(int i=1;i<maxn/2;++i)//因子i
 8         for(int j=i*2;j<maxn;j+=i)//j是i的倍數,即j的因子是i
 9             sum[j]+=i;//sum[j]表示其所有因子之和
10     for(int i=1;i<maxn;++i)
11         if(sum[i]<=1000)f[sum[i]]=true;//如果真因數之和在1000以內,那么sum[i]不是不可摸數
12     while(~scanf("%d",&t)){
13         while(t--){
14             scanf("%d",&n);
15             if(f[n])printf("no\n");
16             else printf("yes\n");//n為不可摸數
17         }
18     }
19     return 0;
20 }

AC代碼二(0ms):

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int t,n;bool f[1005];
 4 int main(){
 5     int obj[89]={2,5,52,88,96,120,124,146,162,188,
 6     206,210,216,238,246,248,262,268,276,288,290,292,
 7     304,306,322,324,326,336,342,372,406,408,426,430,
 8     448,472,474,498,516,518,520,530,540,552,556,562,
 9     576,584,612,624,626,628,658,668,670,708,714,718,
10     726,732,738,748,750,756,766,768,782,784,792,802,
11     804,818,836,848,852,872,892,894,896,898,902,926,
12     934,936,964,966,976,982,996};
13     memset(f,false,sizeof(f));
14     for(int i=0;i<89;++i)f[obj[i]]=true;//1000以內共有89個數為不可摸數
15     while(~scanf("%d",&t)){
16         while(t--){
17             scanf("%d",&n);
18             if(f[n])printf("yes\n");
19             else printf("no\n");
20         }
21     }
22     return 0;
23 }

題解報告:hdu 1299 Diophantus of Alexandria

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
解題思路:首先,根據分式等式的性質可得x、y均大於n,假設y=n+k(k≥1),將其代入1/x+1/y=1/n化簡得x=n^2/k+n,因為x∈N+,所以k|n2(k≥1),即求n2的因子個數sum,則最終的答案為:(sum+1)/2,因為必定有一半的x、y這一對是重復了的,只是值互換了而已,舉個例子:當n=4時,
x= 20  12  8   5
k=  1   2  4  8  16(n^2=16的所有因子)
y=  5   6  8 12  20 
顯然此時有3組解,也就是滿足n2/k == k,(其中k|n2 )的解有(sum+1)/2組。
AC代碼:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;int t;LL n;
 4 LL get_num(LL x){
 5     LL ans=1,tp;
 6     for(LL i=2;i*i<=x;++i){
 7         if(x%i==0){
 8             tp=0;
 9             while(x%i==0)tp++,x/=i;
10             ans*=(1+2*tp);
11         }
12     }
13     if(x>1)ans*=3;
14     return ans;
15 }
16 int main(){
17     while(cin>>t){
18         for(int i=1;i<=t;++i){
19             cin>>n;
20             cout<<"Scenario #"<<i<<":\n"<<(get_num(n)+1)/2<<"\n"<<endl;
21         }
22     }
23     return 0;
24 }

 題解報告:NYOJ #66 分數拆分

描述

現在輸入一個正整數k,找到所有的正整數x>=y,使得1/k=1/x+1/y.

輸入

第一行輸入一個整數n,代表有n組測試數據。
接下來n行每行輸入一個正整數k

輸出

按順序輸出對應每行的k找到所有滿足條件1/k=1/x+1/y的組合。

樣例輸入

2
2 
12

樣例輸出

1/2=1/6+1/3
1/2=1/4+1/4
1/12=1/156+1/13
1/12=1/84+1/14
1/12=1/60+1/15
1/12=1/48+1/16
1/12=1/36+1/18
1/12=1/30+1/20
1/12=1/28+1/21
1/12=1/24+1/24

解題思路:由x>=y且x、y均大於k可知1/x<=1/y,1/k-1/y<=1/y,即k<y<=2k,所以只需控制y的枚舉范圍即可。

AC代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int t,k;
 4 int main(){
 5     while(cin>>t){
 6         while(t--){
 7             cin>>k;
 8             for(int i=k+1;i<=2*k;++i)//枚舉k+1~2k  9                 if(i*k%(i-k)==0)printf("1/%d=1/%d+1/%d\n",k,i*k/(i-k),i);//通分,其中(i-k)|(i*k)。 10         }
11     }
12     return 0;
13 }

財大情侶

Time Limit: 2000/1000ms (Java/Others)

Problem Description:

高考完終於來到夢寐以求的財經大學,男三女七有木有!食堂吃飯前后左右三排都是女生有木有!該學校總共有n個人,每個人都有對應自己的魅力值,從1到n。現規定每個人的情商為每個人魅力值的約數(不包括本身)之和。在廣財有個很神奇的事情,當一個人的情商剛好等於另一個的魅力值的時候,這兩個人就meant to be情侶(不是一男一女怎么辦?隨便吧)。
如:220:1+2+4+5+10+11+20+22+44+55+110=284
   284:1+2+4+71+142=220
這樣魅力值為220和284的就成為一對啦。
給定兩個數,a,b,找出所有a和b之間(inclusive)成對的。

Input:

輸入包含多組測試數據,每組數據輸入兩個數a,b (0<=a,b<=100000).

Output:

對於每組測試,輸出a和b之間的所有情侶。每對情侶占一行,魅力值小的在前面。對於多對情侶,按情侶中魅力值小的排序。參考sample output。

Sample Input:

200 1300
1 200

Sample Output:

220 284
1184 1210
NO
解題思路:求每個數的所有真因子之和,簡單打個表再判斷一下即可。
AC代碼:
 1 #include<bits/stdc++.h>
 2 const int maxn=400005;//范圍大一點,否則會出現越界的情況
 3 using namespace std;
 4 int a,b,x,sum[maxn];bool flag;
 5 int main(){
 6     for(int i=1;i<maxn/2;++i)//求因子數之和
 7         for(int j=i*2;j<maxn;j+=i)//j初始為i的2倍,以后以i的步長增長,累加j的真因子
 8             sum[j]+=i;
 9     while(cin>>a>>b){
10         if(a>b)swap(a,b);flag=false;
11         for(int i=a;i<=b;++i)//先判斷是不是一對情侶,並且前面的因子數之和x要在區間范圍內,且前一個數i要小於后一個數x
12            if(i==sum[x=sum[i]]&&x<=b&&i<x){flag=true;cout<<i<<' '<<x<<endl;}
13         if(!flag)cout<<"NO"<<endl;
14     }
15     return 0;
16 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM