2020年5月第三周

学习内容

本周对数论进行了系统性的学习,对此做一下总结

素数:𝑎>1a>1 且只能被平凡约数整除的数。
合数:𝑎>1a>1 且不是素数的数称为合数。
其他整数(0,1,0,1,负整数)既不是素数也不是合数。

      素数有无穷多个

𝑛n 是一个合数,则 𝑛n 至少有 11 个素因子。因此其中最小的素因子一定不大于 n√n
如果 𝑛n 是合数,则一定可以为分解 𝑎 × 𝑏a×b 的形式,其中 𝑎 𝑏 , 𝑎 ≠1, 𝑏 𝑛a≤b,a≠1,b≠n ,如 18=2×9,18=3×618=2×9,18=3×6 。因 𝑎 × 𝑎 𝑎 × 𝑏 = 𝑛  a×a≤a×b=n  ,则可得: 𝑎 𝑛a≤√n

      可得判断依据:如果 22~𝑛√n 中有 𝑛n 的约数,则 𝑛n 是合数,否则 𝑛n 是素数。

埃拉托斯特尼筛法  :给出 2——N 是自然数表,从前往后筛掉合数,剩下的就是素数。

步骤如下:
首先找到 2为素数,则 2 的倍数一定是合数,筛掉;
后面第一个没有筛掉的数一定是素数,即 3 ,同样筛掉 3 的倍数,以此类推,直到筛掉所有合数为止。


 

#include <stdio.h>
#include <math.h>
 
const int MAX = 10000;//定义n的最大值 
int prime[MAX];
int n; 
/*
	采用埃拉托斯特尼筛算法:
	依次消去2、3、4、5、6、、、、、的倍数,直到没有消的为止;
	每次考虑消去的第一个数p*p,p<=sqrt(n); 
*/ 
void get_prime(){
	for(int i = 2; i <= sqrt(n); i++){
		int k = i;
		for(int j = i * i; j <= n; j = i * k ){
			prime[j] = 0;//将非素数标记为0; 
			k++; 
		}
	}	
}
 
int main() {
	while(scanf("%d",&n) == 1 && n) {
		for(int i = 0; i <= n; i++) {
			prime[i] = i;
		}
		get_prime();
		for(int i = 0; i<=n; i++) {
			if(prime[i] != 0) {
				printf("%5d",prime[i]);
			}
		}
		printf("\n");
	}	
	return 0;
}

 

欧拉筛法 O(n)

inline void sieve(int x) {
	phi[1] = 1;
    for(reg int i = 2;i <= x;i ++) {
        if(! vis[i]) {
        	prim[++ len] = i;
        	phi[i] = i - 1;	//因为欧拉函数代表小于这个数的且与这个数互质的数的个数,所以质数的欧拉函数为它本身减1
        }
        for(reg int j = 1;j <= len && i * prim[j] <= x;j ++) {
            vis[i * prim[j]] = 1;
            if(i % prim[j] == 0) {
            	phi[i * prim[j]] = phi[i] * prim[j];
                break;
            }
            phi[i * prim[j]] = phi[i] * (prim[j] - 1);
        }
    }
}

因数分解

算术基本定理对于每个整数n,都可以唯一分解成素数的乘积,如图所

vector<int> factor(int x) {
	vector<int> ret;
	for (int i = 2; i * i <= x; ++i)
		while (x % i == 0) {
			ret.push_back(i);
			x /= i;
	}
	if (x > 1) ret.push_back(x);
	return ret;
 }

欧几里得算法

计算二个非负整数p和q的最大公约数。若q=0,则最大的公约数为p,否则,将p/q得到的余数r,p和q的最大公约数即为q和r的最大公约数

pubulic static int gcd (int p ,int q)
{
    if(q==0) return p;
    int r = p%q;
    return gcd(q,r);
}

问题解决

Everybody knows any number can be combined by the prime number.
Now, your task is telling me what position of the largest prime factor.
The position of prime 2 is 1, prime 3 is 2, and prime 5 is 3, etc.
Specially, LPF(1) = 0.

Input

Each line will contain one integer n(0 < n < 1000000).

Output

Output the LPF(n).

Sample Input

1
2
3
4
5

Sample Output

0
1
2
1
3

题目大意:每个素数在素数表中都有一个序号,设1的序号为0,则 2
的序号为1(4是2的倍数,所以4的序列也是1),3的序号为2,5的序号为3,以此类推。现在要求输出 所
给定的数n的最大质因子的序号,0 < n < 1000000。

思路:巧用素数打表法。用sum计算素数的序号,将素数连同他的倍数一起置为它的素数序号, 从小到大循环, 这样数组里存放的序号就是最大素数因子的序号了。
注意:初始化时令所有数为0。
再通过sum计算累加,改变之后primeNum[i]为 数 i的最大素数因子的序号。
 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<cmath>
#include<iomanip>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
#define PI acos(-1)

typedef long long ll;
#define N 1000005
int prime[N], cnt;
bool vis[N];
int num[N], e[N], tot = 1;
void init()
{
    for (int i = 2; i <= N; ++i)
    {
        if (!vis[i])
        {
            prime[++cnt] = i;
            num[i] = i + 1;
            e[i] = tot++;
        }
        for (int j = 1; j <= cnt; ++j)
        {
            if (prime[j] * i > N)
                break;
            vis[prime[j] * i] = true;
            e[prime[j] * i] = e[i];
        }
    }
}
int main()
{
    init();

int n;
    while (scanf("%d", &n) != EOF)
    {
        printf("%lld\n", e[n]);
    }
}

A number whose only prime factors are 2,3,5 or 7 is called a humble number. The sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, ... shows the first 20 humble numbers.

Now given a humble number, please write a program to calculate the number of divisors about this humble number.For examle, 4 is a humble,and it have 3 divisors(1,2,4);12 have 6 divisors.
 

Input

The input consists of multiple test cases. Each test case consists of one humble number n,and n is in the range of 64-bits signed integer. Input is terminated by a value of zero for n.

Output

For each test case, output its divisor number, one line per case.

Sample Input

4
12
0

Sample Output

3
6
#include <cstdio>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
LL f[4];
LL n;
bool input()
{
	scanf("%lld", &n);
	if (n == 0) return false;
 	return true;
}
void solve()
{
	f[0] = 1;
 
	while (n % 2 == 0) {
		f[0]++;
		n /= 2;
	}
	f[1] = 1;
	while (n % 3 == 0) {
		f[1]++;
		n /= 3;
	}
 	f[2] = 1;
	while (n % 5 == 0) {
		f[2]++;
		n /= 5;
	}
 	f[3] = 1;
	while (n % 7 == 0) {
		f[3]++;
		n /= 7;
	}
 	LL ans = f[0] * f[1] * f[2] * f[3];
 	printf("%lld\n", ans);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("f:\\OJ\\uva_in.txt", "r", stdin);
#endif
 
	while (input()) {
		solve();
	}
	return 0;
}

七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们的另一半是谁吗?那就按照告示上的方法去找吧!"
人们纷纷来到告示前,都想知道谁才是自己的另一半.告示如下:



数字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

设立一个数组,然后二重循环,i*j的结果就是我们输入的数字,i,j则分别为因子,这样就是由因子找倍数,每次只加上I的值,可以避免重复,这样可以在相应的data[i*j]里面

保存所有的因子,但需要注意,其中也会保存这个数自己,输出的时候需要减去。

#include <iostream>
using namespace std;
int data[500005];
void gcd()
{
    for(int i=1;i<=500000;i++)
    for(int j=1;i*j<=500000;j++)
    data[i*j]+=i;
}
int main()
{ 
    int m,n;
    gcd();
    while(cin>>n)
    {
        while(n--)
        {
            cin>>m;
            cout<<data[m]-m<<endl;
        }
    }
    return 0;
}

东西都比较偏数学,还是要好好学高数

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值