杭电ACM算法入门习题(分解质因子,约数个数,约数之和)

Eddy’s research I(HDU 1164)

Problem Description

Eddy’s interest is very extensive, recently he is interested in prime number. Eddy discover the all number owned can be divided into the multiply of prime number, but he can’t write program, so Eddy has to ask intelligent you to help him, he asks you to write a program which can do the number to divided into the multiply of prime number factor .

Input

The input will contain a number 1 < x<= 65535 per line representing the number of elements of the set.

Output

You have to print a line in the output for each entry with the answer to the previous question.

Sample Input

11
9412

Sample Output

11
2213*181

解题思路:分解质因数模板题。如果当前的数已经是素数,可以直接输出。如果不是素数,则分解质因数。
AC代码

#include <iostream>
#include <cstring>
#include <string>

using namespace std;

int main()
{
    int n;
    while (cin >> n) 
    {
        string res;//用来存出结果
        int pos = 0;//判断当前的因子是否是第一个因子
        
        for (int i = 2;i <= n;i++)
        {
            while (n % i == 0)//找到因子
            {
                if (pos != 0) res += "*";
                res += to_string(i);//将其转化为字符串存储在结果中
                pos ++;
                n /= i;//取出因子之后要更新输入的数
            }
        }
        
        cout << res << endl;
    }
    return 0;
}
反素数(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

解题思路:求解约数的个数模板题
AC代码

#include <iostream>

using namespace std;

/*
//暴力法:返回n的约数个数(time:343MS)
int cal_diviNum(int n)
{
    int sum = 0;
    for (int i = 1;i <= n;i++)//枚举因子
        if (n % i == 0)
            sum ++;
    return sum;
}
*/

//x = p0^k0 + p1^k1 + p2^k2 + ... + pm^km
//约数的个数 = (k0+1) * (k1+1) + (k2+1) + ... + (km+1)  
//(time:15MS)
int cal_diviNum(int n)
{
    int sum = 1;
    
    //枚举质因子,枚举到sqrt(n)即可
    for (int i = 2;i <= n / i;i++)
    {
        int k = 0;//k0 k1 k2 k3 ... km
        while (n % i == 0)//找到了质因子
        {
            k ++;
            n /= i;
        }
        sum *= (k + 1);
    }
    if (n > 1) sum *= (1 + 1);
    return sum;
}

int main()
{
    int T; cin >> T;
    while (T--)
    {
        int a,b; cin >> a >> b;
        int diviNum,ans = -1;
        
        int num = -1;//保存具有最大约数个数的那个数
        for (int i = a;i <= b;i++)
        {
            diviNum = cal_diviNum(i);//计算i约数的个数
            if (ans < diviNum)//如果数字i的约数的个数大于ans
            {
                ans = diviNum;//更新ans
                num = i;
            }
        }
        
        cout << num << endl;
    }
    // cout << cal_diviNum(6) << endl;
    return 0;
}
七夕节(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

解题思路:求解约数之和模板题。本题需要注意的是12的约数本来有1、2、3、4、6、12,但是在本题中约数不包括它本身。另外本题数据量大,因此需要使用scanf以及printf
AC代码

#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;
const int N = 500005;
int vis[N],prime[N],pcnt;

void init()//埃氏筛模板
{
    vis[0] = vis[1] = 1;//0、1不是质数
    for (int i = 2;i < N;i++)
    {
        if (!vis[i])//vis[i]==0表示i是质数
        {
            prime[pcnt++] = i;
            for (int j = i + i;j < N;j += i)
                vis[j] = 1;//j不是质数
        }
    }
}

int cal_diviSum(int n)//计算n的约数之和
{
    int result = 1;
    for (int i = 0;i < pcnt && prime[i] <= n / prime[i];i++)//一个有"=",一个没"="
    {
        int cnt = 0;//约数pi的个数
        while (n % prime[i] == 0)//找到约数
        {
            cnt++;//统计质因子的个数
            n /= prime[i];//更新n的值
        }
        
        //质因子prime[i]有cnt个
        int sum = 0,base = 1;
        for (int j = 0;j <= cnt;j++)
        {
            sum += base;
            base *= prime[i];
        }
        
        result *= sum;
    }
    
    //如果最后n > 1,说明还剩一个质数
    if (n > 1) result *= (1 + n);
    
    return result;
}

int main()
{
    init();//先筛质数
    int T; scanf("%d",&T);
    while (T --)
    {
        int n; scanf("%d",&n);
        printf("%d\n",cal_diviSum(n) - n);//本题中约数不包括自己
    }
    /*
    for (int i = 0;i <= 10;i++) cout << prime[i] << " ";
    2 3 5 7 11 13 17 19 23 29 31 
    */
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值