单求欧拉函数
ll phi(ll n)
{
ll ans = n;
for(int i = 2; i * i <= n; i++)
{
if(n % i == 0)
{
ans -= ans / i;
while(n % i == 0)
n /= i;
}
}
if(n > 1) ans -= ans / n;
return ans;
}
欧拉函数线性筛
void euler()
{
phi[1] = 1;
for(int i = 2; i < maxn; i++)
{
phi[i] = i;
}
for(int i = 2; i <= maxn; i++)
{
if(phi[i] == i)
for(int j = i; j < maxn; j += i)
phi[j] = phi[j] /i * (i - 1);
}
}
性质:
1.添加链接描述
素数筛线性筛
const int maxn =1e6 + 7;
int tot;
bool valid[maxn];
int prime[maxn];
void getPrime()
{
memset(valid, true, sizeof(valid));
valid[1] = valid[1] = false;
tot = 0;
for(int i = 2; i < maxn; i++)
{
if(valid[i])
prime[tot++] = i;
for(int j = 1; j < tot && i * prime[j] < maxn; j++)
{
valid[i * prime[j]] = false;
if(i % prime[j] == 0) break;
}
}
}
//用线性筛求莫比乌斯函数
void getmiu()
{
tot = 0;
memset(valid, true, sizeof(valid));
valid[0] = valid[1] = false;
miu[1] = 1;
sumu[1] = 1;
for(int i = 2; i < maxn; i++)
{
if(valid[i])
{
prime[tot++] = i;
miu[i] = -1;
}
for(int j = 0; j < tot && prime[j] * i < maxn; j++)
{
valid[prime[j] * i] = false;
if(i % prime[j] == 0)
{
miu[i * prime[j]] = 0;
break;
}
else
miu[i * prime[j]] = -miu[i];
}
sumu[i] = sumu[i - 1] + miu[i];
}
}
扩展欧几里得
int exgcd(int a, int b, int &x, int &y)
{
if(b == 0)
{
x = 1, y = 0;
return a;
}
int r = exgcd(b, a % b, y, x);
y -= x * (a / b);
return r;
}
解方程组 ax + by = c % b, c 为gcd(a, b) 的倍数
扩展kmp
char s[maxn], t[maxn];
int exend[maxn], exnext[maxn];
void getNext(char *t)
{
int len = strlen(t);
exnext[0] = len;
int p = 0, a = 0;
for(int i = 1; i < len; i++)
{
if(i >= p || i + exnext[i - a] >= p)
{
if(i >= p)
p = i;
while(p < len && t[p] == t[p - i])
p++;
a = i;
exnext[i] = p - i;
}
else
exnext[i] = exnext[i - a];
}
}
void exkmp(char *s, char *t)
{
int m = strlen(t);
int n = strlen(s);
getNext(t);
int p = 0, a = 0;
for(int i = 0; i < n; i++)
{
if(i >= p || exnext[i - a] + i>= p)
{
if(i >= p)
p = i;
while(p - i < m && p < n && t[p - i] == s[p])next
p++;
a = i;
exend[i] = p - i;
}
else
exend[i] = exnext[i - a];
}
}
kmp
void getnext(int n)
{
int k = -1, j = 0;
nex[0] = -1;
while(j < n)
{
if(k == -1 || p[k] == p[j])
{
j++, k++;
if(p[k] != p[j]) nex[j] = k;
else nex[j] = nex[k];
}
else
k = nex[k];
}
}
int kmp(int n, int m)
{
int j = 0, i = 0;
while(i < n && j < m)
{
if(j == -1 || p[j] == s[i])
{
i++, j++;
}
else j = nex[j];
}
if(j == m)
return i - m + 1;
else return -1;
}
马拉车
char s[maxn];
int p[maxn<<1];
char man[maxn<<1];
int init(char *s)
{
int len = strlen(s);
man[0] = '$';
man[1] = '#';
int j = 2;
for(int i = 0; i < len; i++)
{
man[j++] = s[i];
man[j++] = '#';
}
man[j] = 0;
return j;
}
void manacher(char *s)
{
int len = init(s);
int mx = 0, id;
for(int i = 1; i < len; i++)
{
if(i < mx)
p[i] = min(mx - i, p[2 * id - i]);
else
p[i] = 1;
while(man[i + p[i]] == man[i - p[i]])
p[i]++;
if(i + p[i] > mx)
{
id = i;
mx = i + p[i];
}
}
}
分块
void build(int n)
{
int block = sqrt(n);
int num = n / block;
if(n % block) num++;
for(int i = 1; i <= num; i++)
{
l[i] = (i - 1) * block + 1;
r[i] = i * block;
}
r[num] = n;
for(int i = 1; i <= num; i++)
for(int j = l[i]; j <= r[i]; j++)
belong[j] = i;
}
void update(int x, int y)
{
if(belong[x] == belong[y])
{
for(int i = x; i <= y; i++)
a[i]++;
}
else
{
for(int i = x; i <= r[belong[x]]; i++)
{
a[i]++;
}
for(int i = belong[x] + 1; i < belong[y]; i++)
time[i]++;
for(int i = l[belong[y]]; i <= y; i++)
a[i]++;
}
}
快速幂和龟速乘(两者结合加速防爆炸)
ll q_pow(ll x, ll y, ll mod)
{
ll sum = 1;
while(y)
{
if(y & 1) sum = (sum * x) % mod;
x = x * x % mod;
y >>= 1;
}
return sum;
}
ll q_mul(ll x, ll y, ll mod)
{
ll ans = 0;
while(y)
{
if(y & 1) ans += x, ans %= mod;
x = x + x;
x %= mod;
y >>= 1;
}
return ans;
}
卢卡斯
ll lucas(ll n, ll m,ll mod)
{
if(m == 0)
return 1;
return C(n % mod, m % mod, mod) * lucas(n / mod, m / mod, mod) % mod;
}
中国剩余定理
ll crt(ll m[], ll a[], int n)
{
ll M = 1, ans = 0, x, y, Mi;
for(int i = 1; i <= n; i++)
M *= m[i];
for(int i = 1; i <= n; i++)
{
Mi = M / m[i];
exgcd(Mi, m[i], x, y);
x = (x % m[i] + m[i]) % m[i];
ans = (ans + a[i] * Mi * x) % M;
}
return (ans % M + M) % M;
}
中国剩余定理非互质
typedef long long ll;
ll m[maxn], a[maxn];
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if(!b)
{
x = 1, y = 0;
return a;
}
ll r = exgcd(b, a % b, y, x);
y -= x * (a / b);
return r;
}
ll excrt(ll m[], ll a[], int n)
{
ll M = m[1], c = a[1], x, y, gcd;
for(int i = 2; i <= n; i++)
{
gcd = exgcd(M,m[i], x, y);
if((a[i] - c) % gcd) return -1;
x = (a[i] - c) / gcd * x % m[i];
c = c + M * x;
M = M / gcd * m[i];
c %= M;
}
return (c % M + M) % M;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; i++)
{
scanf("%lld%lld", m + i, a + i);
}
ll ans = excrt(m, a, n);
printf("%lld\n", ans);
}
return 0;
}
st表、
int a[maxn];
int st[maxn][30];
void init(int n)
{
for(int i = 0; i < n; i++)
st[i][0] = a[i];
for(int j = 1; (1 << j) <= n; j++)
{
for(int i = 0; i + (1 << j) - 1 < n; i++)
st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1)][j - 1]);
}
}
int get(int l, int r)
{
int k = (int)(log(r - l + 1)/ log(2.0));
return min(st[l][k], st[r - (1 << k) + 1][k]);
}
矩阵快速幂
typedef long long ll;
const int mod = 1e9 + 7;
ll fast_mul(ll a, ll b)
{
ll res = 0;
while(b)
{
if(b & 1) res = (res + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return res;
}
struct marx
{
ll mar[2][2];
marx()
{
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
mar[i][j] = 0;
}
mar[i][i] = 1;
}
}
marx operator * (const &a)
{
marx res;
for(int i = 0, i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
int sum = 0;
for(int k = 0; k < 2; k++)
{
sum = (sum + fast_mul(mar[i][k], a.mar[k][j])) % mod;
}
res.mar[i][j] = sum;
}
}
return res;
}
};
匈牙利算法
bool hungry(int x)
{
for(int i = m + 1; i <= n; i++)
{
if(!mp[x][i]) continue;
if(!used[i])
{
used[i] = true;
if(!_pair[i] || hungry(_pair[i]))
{
_pair[i] = x;
// printf("21213\n");
return true;
}
}
}
return false;
}
for(int i = 1; i <= n; i++)
{
memset(used, false, sizeof(used));
if(hungry(i))
ans++;
}
未完待续