爷的第一篇CSDN博客!

爷的第一篇CSDN博客!

ZCMU-1409
1409: 因子和
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 329 Solved: 90
[Submit][Status][Web Board]
Description
求一个数的因子和很简单,所以小明很懒就想让你帮忙算一下区间a到b中哪个数的因子和最大,并输出这个数和他的每个因子。

Input
输入a和b,(0<a<=b<10^6).

Output
输出这个数和他的每个因子(相同情况输出最小的),因子从小到大输出。

Sample Input
1 10
Sample Output
10 = 1 + 2 + 5

前言

这是菜狗入学来第一篇博客,今天就简单记录下素数筛的简单应用吧!
(作为一名ACMer,要养成写博客的习惯啊!)

一、素数筛是什么?

1.算术基本定理:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积
2. 若一个数可以进行因数分解,则得到的两个数一定是有一个>=sqrt(x),另一个<=sqrt(x).

依照我的理解,就是将数字从2到maxn遍历,然后将后面的这些数的因子记录下来,就像个筛子一样,以此做到减少时间复杂度的作用,大大提高效率

二、如何使用?

这是素数筛执行的函数,看一遍基本就懂了,这里写在这里就是为了防止忘记,好记性不如烂笔头对吧!

int prime[maxn];
void isprime()
{
    int i,j;
    memset(prime,1,sizeof(prime));
    for(i=2;i<=maxn/2;i++)
        for(j=i+i;j<maxn;j+=i)
            prime[j]=0;
}

总结

以下是AC代码,其实如果知道素数筛的话也就是个水题

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int arr[maxn],sum[maxn];
int t = 0;
void getsum()//素数筛法,预处理每一个数的因子和,后面只要查找就行了,不用重复计算
{
    int i,j;
    memset(sum,1,sizeof(sum));
    for(i = 2;i <= maxn / 2;i++)
    {
        for(j = i + i;j < maxn;j += i)
            sum[j] += i;
    }
}
int main(){
    
        getsum();
        int a,b;
        while(~scanf("%d%d",&a,&b))
        {
            int maxsum = 0,dis = 0;
            for(int i = a;i <= b;i++)
            {
                if(sum[i] > maxsum)
                {
                    maxsum = sum[i];
                    dis = i;//记录因子和最大的那个数
                }
                
            }
            printf("%d = 1",dis);
            for(int i=2;i<=dis/2;i++)
                if(dis % i==0)printf(" + %d",i);
            cout << endl;
        }
    return 0;
    }

就这样吧。
感觉写博客还挺有意思的,还可以梳理一遍知识,争取一天一篇!


4月6号补充一道题目

ZCMU-1039
1039: 二哥的困惑 Ⅱ

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 552 Solved: 278
[Submit][Status][Web Board]
Description

In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture:

Every even number greater than 4 can be
written as the sum of two odd prime numbers.

For example:

8 = 3 + 5. Both 3 and 5 are odd prime numbers.
20 = 3 + 17 = 7 + 13.
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.

Today it is still unproven whether the conjecture is right. (Oh wait, I have the proof of course, but it is too long to write it on the margin of this page.)
Anyway, your task is now to verify Goldbach’s conjecture for all even numbers less than a million.

Input

The input will contain one or more test cases.
Each test case consists of one even integer n with 6 <= n < 1000000.
Input will be terminated by a value of 0 for n.

Output

For each test case, print one line of the form n = a + b, where a and b are odd primes. Numbers and operators should be separated by exactly one blank like in the sample output below. If there is more than one pair of odd primes adding up to n, choose the pair where the difference b - a is maximized. If there is no such pair, print a line saying “Goldbach’s conjecture is wrong.”

Sample Input

8
20
42
0

Sample Output

8 = 3 + 5
20 = 3 + 17
42 = 5 + 37

这道题其实也差不多,就是把所有素数先筛出来存入DP数组,然后查找n是否可以由两素数组成的j和n-j组成

题干里说b-a要尽量大,由于b-a推导是n-2j,那么j足够小也就是从小到大遍历找到的就是b-a最大的


AC代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pre(i,a,b) for(int i=a;i>=b;--i)
#define m(x) memset(x,0,sizeof x)
typedef long long ll;
const int maxn = 1e6+10;
#define PI acos(-1)
int DP[maxn]={0};//是disposal啦,不是dynastic prosess
//预处理素数筛
void PreDisposal()
{
    for(int j=2;j<maxn/2;++j)
    if(!DP[j])
        for(int i=2*j;i<maxn;i+=j)
        DP[i] = 1;
}
int main()
{
    int n,flag;
    PreDisposal();
    DP[1] = DP[2] = 1;
    while(~scanf("%d",&n)&&n)
    {
        flag = 0;
        for(int j=2;j<maxn;j++)
        {
            if(!DP[j]&&!DP[n-j])
            {
                printf("%d = %d + %d\n",n,j,n-j);
                flag = 1;
                break;
            }
        }
        if(!flag)printf("Goldbach's conjecture is wrong.\n");  
    }
    return 0;
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值