数论板子
数论分块 :
j = n / (n / i);
ans += (n/i) * (j - i + 1);
筛法:
线性筛:
#include<cstring>
#incldue<cmath>
const int MAXN=1000010;
bool prime[MAXN];
int Prime[MAXN];
int num=0;
void make_prime()
{
memset(prime,true,sizeof(prime));
prime[0]=prime[1]=false;
for(int i=2;i<=MAXN;i++)
{
if(prime[i])
{
Prime[num++]=i;
}
for(int j=0;j<num&&i*Prime[j]<MAXN;j++)
{
prime[i*Prime[j]]=false;
if(!(i%Prime[j]))
break;
}
}
return;
}
杜教筛:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<tr1/unordered_map>
using namespace std;
using namespace std::tr1;
int read(void) {
int x = 0;
char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) {
x = (x << 3) + (x << 1) + c - '0';
c = getchar();
}
return x;
}
int T, n;
#define ll long long
const int N = 7000005;
ll sum_phi[N];
int sum_mu[N];
int prime[2000005];
bool vis[N];
int tot;
int maxn = 7000000;
void pre(void) {
sum_phi[1] = sum_mu[1] = 1;
for (int i = 2;i <= maxn; i++) {
if (!vis[i]) {
prime[++tot] = i;
sum_phi[i] = i - 1;
sum_mu[i] = -1;
}
for (int j = 1;j <= tot && prime[j] * i <= maxn; j++) {
int tmp = i * prime[j];
vis[tmp] = 1;
if (i % prime[j]) {
sum_phi[tmp] = sum_phi[i] * (prime[j] - 1);
sum_mu[tmp] = -sum_mu[i];
}
else {
sum_phi[tmp] = sum_phi[i] * prime[j];
break;
}
}
}
for (int i = 2;i <= maxn; i++)
sum_phi[i] += sum_phi[i-1],
sum_mu[i] += sum_mu[i-1];
}
unordered_map<int,ll> f_mu, f_phi;
ll phi(int x) {
if (x <= maxn) return sum_phi[x];
if (f_phi[x]) return f_phi[x];
ll ans = (1 + (ll)x) * (ll)x / 2;
int p;
for (int l = 2, r;l <= x; l = r + 1) {
p = x / l;
r = x / p;
ans -= (r - l + 1) * phi(p);
}
return f_phi[x] = ans;
}
int mu(int x) {
if (x <= maxn) return sum_mu[x];
if (f_mu[x]) return f_mu[x];
int ans = 1;
int p;
for (int l = 2, r;l <= x; l = r + 1) {
r = x / (p = x / l);
ans -= (r - l + 1) * mu(p);
}
return f_mu[x] = ans;
}
int main() {
pre();
T = read();
while (T--) {
n = read();
printf ("%lld %d\n", phi(n), mu(n));
}
return 0;
}
拓展欧几里得:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int x, y, a, b;
void gcd(int m,int n) {
int k = m / n, p = m % n;
if (p == 1) {
x = -k, y = 1;
return;
}
gcd(n, p);
int z = y;
y = x,x = z - x * k;
}
int main() {
scanf ("%d %d", &a, &b);
gcd(a, b);
cout << (y % b + b) % b;
return 0;
}
乘法逆元(线性) :
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 3006000;
#define ll long long
ll inv[N];
int main() {
int n, p; cin >> n; cin >> p;
inv[1] = 1;
cout << 1 << endl;
for (int i = 2;i <= n; i++) {
inv[i] = (p - (p / i)) * inv[p % i] % p;
printf ("%lld\n", inv[i]);
}
return 0;
}
快速幂(???) :
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long s;
long long a,k;
long long fuc(long long b)
{
if(b==1) return a;
if(b==0) return 1;
long long h=fuc(b/2)%k;
if(b%2==0) return h*h;
else return h*h*a;
}
int main()
{
long long b;
cin>>a>>b>>k;
cout<<a<<"^"<<b<<" mod "<<k<<"="<<fuc(b)%k;
return 0;
}
原文地址:https://www.cnblogs.com/Hs-black/p/11626119.html
时间: 2024-10-09 20:43:53