基礎數論

一、負進制數

\quad將一個整數R進制分開,R爲負數。例如-15的-2進制如下:
在這裏插入圖片描述
程序輸入爲整數N和負整數R,輸出其R進制(-R<36)。大於10的數用A-Z表示。

// 負進制轉換,即R爲負數
#include <iostream>
#include <vector>
using namespace std;

int main(int argc, char const *argv[])
{
	int N, R; cin >> N >> R;
	int n = N;
	vector<char> res;
	do{
		int M = N%R;
		if(M<0) M -= R, N += R;
		char t = M+'0';
		if(M>=10) t = M-10+'A';
		res.push_back(t);
		N /= R;
	}while(N);
	cout << n << "=";
	for(int i = res.size()-1; i >= 0; i--) cout << res[i];
	cout << "(base" << R << ")";
	return 0;
}

二、有序全排列next_permutation

\quad輸入數個數N和需要經過M次全排列,接着輸入這n個數,輸出M次全排列後的順序

// next_permutation的用法
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e4+10;
int a[maxn];
int main(int argc, char const *argv[])
{
	int N, M; cin >> N >> M;
	for(int i = 0; i < N; i++) cin >> a[i];
	while(M--) next_permutation(a, a+N);
	for(int i = 0; i < N; i++) cout << a[i] << " ";
	return 0;
}

三、求連續自然數和

\quad輸入一個數M,輸出M可以爲哪些連續整數求和得到,比如1998+1999+2000+2001+2002=10000,所以從1998到2002的一個自然數段爲M=10000的一個解。

輸入:
10000
輸出:
18 142 
297 328 
388 412 
1998 2002
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1e6+10;
long long sum[maxn];
int main(int argc, char const *argv[])
{
	int M; cin >> M;
	for(int i = 1; i < maxn; i++) sum[i] = sum[i-1]+i;
	for(int i = 0; i < maxn && i < M/2+1; i++){
		long long key = M+sum[i];
		int index = lower_bound(sum, sum+maxn, key)-sum;
		while(sum[index]>key) index--;
		if(sum[index]==key) cout << i+1 << " " << index << endl;
	}
	return 0;
}

四、求[1,n]這n個數有多少個約數

在這裏插入圖片描述

// 求[1,n]有多少個約數
// [1,n]是i的倍數的數有int(n/i)個,故暴力枚舉int(n/i),i從1-n,累加即可
#include <iostream>
using namespace std;

int main(int argc, char const *argv[])
{
	int n; cin >> n;
	long long res = 0;
	for(int i = 1; i <= n; i++){
		res += (int)(n/i);
	}
	cout << res << endl;
	return 0;
}

五、查詢區間[l,r]內素數個數

\quad首先預處理[1,m]內素數,放在一個數組裏,每次查詢都可以用二分查。

// 區間查詢[l,r]內素數個數,可以篩出素數存在數組裏面然後用二分查,也可以用前綴和數組存儲表示1-i有多少個素數a[i]
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1e6+10;
int isPrime[maxn], prime[maxn];
int getPrime()
{
	isPrime[1] = 1;
	int index = 0;
	for(int i = 2; i < maxn; i++)
	{
		if(isPrime[i]==0) prime[index++] = i;
		for(int j = i+i; j < maxn; j+=i)
			isPrime[j] = 1;
	}
	return index;
}
int main(int argc, char const *argv[])
{
	int n, m; cin >> n >> m;
	int num = getPrime();
	while(n--)
	{
		int l, r; cin >> l >> r;
		if(l<1 || r>m) cout << "Crossing the line" << endl;
		else{
			int begin = lower_bound(prime, prime+num, l)-prime;
			int end = lower_bound(prime, prime+num, r)-prime;
			if(prime[end]==r) end++;
			cout << end-begin << endl;
		}
	}
	return 0;
}

六、求2P2^P有多少位,並求出其最後500位

\quadaba^b位數爲(log10a)b+1(log_{10}a)*b+1,求其最後500爲需結合高精度和快速冪運算。

// 高精度和快速冪
#include <iostream>
#include <cmath>
#include <cstring>
#include <vector>
using namespace std;
vector<int> mul(vector<int> a, vector<int> b)
{
	vector<int> c(1000);
	for(int i = 0; i < 500; i++)
		for(int j = 0; j < 500; j++)
			c[i+j]+=a[i]*b[j];
	for(int i = 0; i < 500; i++) c[i+1]+=c[i]/10, c[i]%=10;
	return c;
}
int main()
{
	int P; cin >> P;
	int len = log10(2)*P+1;
	cout << len << endl;
	vector<int> a(1000, 0), b(1000, 0), res(1000, 0);
	res[0] = 1,  b[0] = 2;
	while(P)
	{
		if(P%2==1) res = mul(res, b);
		P /= 2;
		b = mul(b, b);
	}
	for(int i = 499; i >= 0; i--) cout << res[i];
	return 0;
}

七、快速冪

\quadab%ma^b\%m的值

#include <bits/stdc++.h>
using namespace std;

int main(int argc, char const *argv[])
{
	int a, b; cin >> a >> b;
	int m=1025*1025, res = 1;
	while(b)
	{
		if(b%2==1) res = (res*a)%m;
		b /= 2;
		a = (a*a)%m;
	}
	cout << res << endl;
	return 0;
}

八、最大公約數gcd

\quad求a和b的最大公約數

/*
歐幾里得算法:gcd(a,b)=gcd(b,a%b)
這個的證明就不再展開,因此程序遞歸到b爲0時終止,返回a即可
*/

#include <bits/stdc++.h>
using namespace std;
int gcd(int a, int b)
{
	if(b==0) return a;
	else return gcd(b, a%b);
}

int main(int argc, char const *argv[])
{
	cout << gcd(49, 2100) << endl;
	return 0;
}

九、求n!n!內有多少個質因子P

/*
求n!中有多少個質因子p?
方法一:n!=1*2*3*...*n,分別統計1到n中包含多少個質因子p,累加即可,時間複雜度爲O(nlogn)
方法二:n!有(n/p+n/(p^2)+n/(p^3)+...)個質因子p,時間複雜度爲O(logn)

note:n!後面有多少個0即爲求n!中質因子爲5的個數
*/
#include <bits/stdc++.h>
using namespace std;

//方法一
int cal(int n, int p)
{
	int res = 0;
	for (int i = 2; i <= n; ++i)
	{
		int temp = i;
		while(temp%p==0)
		{
			res++;
			temp /= p;
		}
	}
	return res;
}

// 方法二
int cal2(int n, int p)
{
	int res = 0;
	while(n)
	{
		res += n/p;
		n /= p;
	}
	return res;
}


int main(int argc, char const *argv[])
{
	cout << cal(100000, 10) << endl;
	cout << cal2(10, 5) << endl;
	return 0;
}

十、質因子分解

/*
質因子分解是指將一個正整數n分解爲一個或者多個質數乘積的形式,例如6=2*3,180=2*2*2*3*5
對於n來說,如果存在[2,n]範圍內的質因子,則這些質因子全部小於等於sqrt(n);或者只存在一個大於sqrt(n)的質因子
因此只需要枚舉到sqrt(n)即可
*/

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5+10;
struct factor
{
	int x, cnt; // x爲質因子,cnt爲其個數
}fac[10];

int prime[maxn];
void set_prime()
{
	for (int i = 2; i < maxn; ++i)
	{
		for (int j = i; j*i < maxn; ++j)
		{
			prime[j*i] = 1;
		}
	}
}

void slove(int n)
{
	int num = 0;
	for (int i = 2; i < sqrt(n+1); ++i)
	{
		if(prime[i]==0 && n%i==0)
		{
			fac[num].x = i;
			fac[num].cnt = 0;
			while(n%i==0)
			{
				fac[num].cnt++;
				n /= i;
			}
			num++;
		}
		if(n==1) break; //及時退出循環
	}
	if(n!=1)
	{
		fac[num].x = n;
		fac[num].cnt = 1;
	}
}

int main(int argc, char const *argv[])
{
	int n;
	while(cin >> n)
	{
		slove(n);
		for (int i = 0; i < 10; ++i)
		{
			if(fac[i].x==0) break;
			cout << fac[i].x << ":" << fac[i].cnt << " ";
			fac[i].x = fac[i].cnt = 0;
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章