1. 整数論
1.1 素数
定義: 1 より大きいすべての自然数は、1 とそれ自体の約数が 2 つしか含まれていない場合、素数 (素数) と呼ばれます。
素数判定裁判部門
bool is_prime(int n)
{
if(n < 2) return false;
for(int i = 2;i <= n / i;i ++)
{
if(n % i == 0)
return false;
}
return true;
}
素因数
基本的な考え方: n のすべての約数を小さいものから大きいものまで列挙します。
void divide(int n)
{
for(int i = 2;i <= n;i ++)
{
if(n % i == 0)
{
int s = 0;
while(n % i == 0)
{
n /= i;
s ++;
}
printf("%d %d\n",i,s)
}
}
}
ふるい法
#include<iostream>
#include<algorithm>
using namespace std;
int primes[N],cnt;
bool st[N];
void get_prime(int n)
{
for(int i = 2;i <= n;i ++)
{
if(!st[i])
{
primes[cnt ++] = n;
for(int j = i + i;j <= n;j += i) st[j] = true;
}
}
}
リニアふるい
各数値が最小の素因数によって除外されることが保証されます。
#include<iostream>
#include<algorithm>
using namespace std;
int primes[N],cnt;
bool st[N];
void get_primes(int n)
{
for(int i = 2;i<= n;i ++)
{
if(!st[i]) primes[cnt ++] = i;
for(int j = 0;primes[j] <= n / i;j ++)
{
st[primes[j] * i = true;
if(i % primes[j] == 0) break; //primes[j]一定是i的最小质因子
}
}
}
1.2 近似
試行分割法
vector<int> get_divisors(int n)
{
vector<int> res;
for(int i = 1;i <= n / i;i ++)
if(n % i == 0)
{
res.push_back(i);
if(i != n / i) res.push_back(n / i);
}
sort(res.begin(),res.end());
return res;
}
約数と約数の和
ユークリッドアルゴリズム
//返回a与b的最大公约数
int gcd(int a,int b)
{
return b ? gcd(b,(a % b) : a);
}
2. オイラーの定理
2.1 オイラー関数
定義: X(n) は、n と互いに素な 1~n の数を表します。
アルゴリズムのステップ:
- 1~N から p1,p2,...,pk の倍数を削除します
- Pi*Pj のすべての倍数を加えたもの
- Pi*Pj*Pk の倍数をすべて減算します。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
while(n --)
{
int a;
cin>>a;
int res = a;
//分解质因数
for(int i = 2 ;i <= a;i ++)
{
if(a % i == 0)
{
res = res / i * (i - 1);
while (a % i == 0) a /= i;
}
}
if(a > 1) res = res / a * (a - 1);
cout<<res<<endl;
}
return 0;
}
高速パワー
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
//求a^k % p
int main(int a,int k,int p)
{
int res = 1;
while(k)
{
//如果当前k的末位为1,则
if( k & 1) res = (LL)res * a % p;
//删除k的末位
k >>= 1;
//把a平方
a = (LL) a * a % p;
}
return res;
}
int main()
{
int n;
scanf("%d",&n);
while(n --)
{
int a,k,p;
scanf("%d%d%d",&a,&k,&p);
printf("%d\n",qmi(a,k,p));
}
return 0;
}