目录
HDU6069 Counting Divisors(区间分解质因数)
HDU 5869 Different GCD Subarray Query
POJ3090 Visible Lattice Points
POJ3530 A Modular Arithmetic Challenge
POJ2891 Strange Way to Express Integers
Different GCD Subarray Query代码
A Modular Arithmetic Challenge代码
Strange Way to Express Integers代码
质数
质数的判定
试除法
若一个正整数 N 为合数,则一定存在一个能整除 N 的数字
MillerRobbin(米勒罗宾素数测试)
大于2的素数n,存在,d为奇数
以下任一条件成立,n为素数,a为任意整数
typedef long long LL;
bool check(LL a, LL n) {
LL m = n - 1, x, y;
int i, j = 0;
while (~m & 1)m >>= 1, j++;
x = quickpow(a, m, n); //快速幂
for (i = 1; i <= j; x = y, i++) {
y = quickpow(x, 2, n);
if (y == 1 && x != 1 && x != n - 1)
return true;
}
return y != 1;
}
bool miller_rabin(int times, int n) {
LL a;
if (n == 1)return false;
if (n == 2) return true;
if (~n & 1)return false;
while (times--)
if (check(rand() % (n - 1) + 1, n))
return false;
return true;
}
素数筛法
埃氏筛
任意x的倍数都不是素数
线性筛
埃式筛法对同一个合数多次标记导致耗时非线性,比如
线性筛法通过唯一标记合数的方式来优化埃氏筛
for (int i = 2; i <= N; i++) {
if (!vis[i])prime[cnt++] = i;
for (int j = 0; j < cnt&&prime[j] * i <= N; j++) {
vis[prime[j] * i] = true;
if (i%prime[j] == 0)
break;
}
}
区间筛
一个合数 n 一定包含一个不超过 的质因数
用筛法求出 以内的质数
用这些质数去标记 [L,R] 中的合数,未被标记的就是质数
const int maxm = 1000000;
bool v[maxm];
void interval_sieve(int l, int r) {
memset(v,0,sizeof(v));
if (l == 1)v[0] = true;
for (int i = 0; i < cnt; i++) {
for (int j = (l - 1) / prime[i] + 1; j <= r / prime[i]; j++) {
if (j > 1) v[prime[i] * j - l] = true;
}
}
}
Prime Distance
给定整数L,R,求区间相邻两个质数的差最大是多少?
板子题
HDU6069 Counting Divisors(区间分解质因数)
求
积性函数
因子数
则
本题要用到区间筛法对L-R分解质因数
阶乘分解
阶乘 N!中包含质因子 x 的个数为
ural1055 Combinations
求 Cm n (1 ≤n,m≤ 5∗105) 的不同质因子个数
分别求分子质因子个数和分母质因子个数,若分子个数比分母多则有效
约数
算术基本定理的扩展
约数个数
约数之和
数值分块
BZOJ1257 余数之和
给定正整数n,k,计算
当时,最多只有个取值
当时,最多只有个取值
综上最多只有个取值,且数值单调递减,可以数值分块
BZOJ2956 模积和
求
第一项与第二项与上题同
最大公约数
(a,b互质)
欧几里得算法
设 a = q∗b+r,其中 r = a mod b
对于 a,b 的任意公约数 d,d|a,d|q*b
则 d|(a-q*b),即 d|r
int gcd(int a,int b){
return b? gcd(b,a%b):a;}
}
区间GCD
当固定区间的右端点,区间左端点越小,区间的GCD就越小,区间GCD的变化次数至多等于右端点的质因子数
a1=1, a2=2, a3=4, a4=6
从小到大枚举右端点,计算左端点的分界线,表示对于右端点,左端点属于时区间gcd都是相同的
在枚举的过程中,可以利用右端点在时数组的计算结果,因为区间内多一个数字时,区间GCD的段数单调不增,可以通过右端点在时候的分段合并得到
a5=9
复杂度
//a[i]为数组
//l[j]表示l[j]-j的区间gcd相同
//v[j]表示l[j]-j的区间gcd的值
for (int i = 1; i <= n; i++) {
for (v[i] = a[i], j = l[i] = i; j; j = l[j] - 1) { //通过l[j]移动
v[j] = gcd(v[j], a[i]);
while (l[j] > 1 && gcd(a[i], v[j] - 1) == gcd(a[i], v[j])) //若两个区间gcd相同则合并
l[j] = l[l[j] - 1];
}
}
HDU 5726 GCD
给出数组a,询问L,R的区间gcd的值和与L,R区间gcd相同的组数
枚举i的右端点,将所有的l[j]和v[j]分别存储(本题相同值的组数要开longlong!!!)
HDU 5869 Different GCD Subarray Query
求L-R区间内区间gcd的值的数量
转化为求区间内颜色数量的问题,可以用离线树状数组或者主席树做,不会的可以看道例题学习下,洛谷 HH的项链
那么这题需要考虑的是怎么把区间的颜色转化到点上?
我们通过区间gcd可以知道L【j】- j的颜色,即只要包含右边界,就可以取到x
所以增加一个区间,相当于j点增加一种颜色
欧拉函数
欧拉函数 ϕ(N):1 到 N 中与 N 互质的数字个数
对于质数p,
若a为质数,
//什么意思我也不懂 qwq
大概意思应该是n的所有因数的欧拉函数和为n
分解质因数求欧拉函数
int phi(int n){
int ans=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
线性筛求质因数
/*
特性 :
1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])
*/
bool vis[maxn+5];
int prime[maxn+5],cnt;
int phi[maxn+5];
void Phi() {
phi[1]=1;
vis[1]=true;
for(int i=2; i<=maxn; i++) {
if(!vis[i]) prime[cnt++]=i,phi[i]=i-1;
for(int j=0; j<cnt&&prime[j]*i<=maxn; j++) {
vis[prime[j]*i]=1;
if(i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
POJ2478 Farey Sequence
求n以内的互质数对
欧拉函数求和,板子题
POJ3090 Visible Lattice Points
二维坐标站在(0,0)点上,能看到第一象限哪些点
看到的点的x,y都是互质的,考虑x,y轴和对角线
POJ2480 Longge's problem
求
枚举GCD
统计的个数,发现其个数为
因为x为N的因数,gcd(i,N)=x,i应与互质
欧拉函数是非完全积性函数,积性函数的约数和也是积性函数
若a为质数,b mod a=0,phi[a*b]=phi[b]*a
BZOJ 4804 欧拉心算 心酸
求
统计的个数,为
即若gcd(i,j)==x,则与互质
与上文中的Visible Lattice Points很像,即为二维坐标上互质的点,
综上,结论为,在来一波等值分块就能过了
HDU5780 gcd
求
先套一波上面的公式
同上题,取
并等值分块
HDU4676 Sum Of Gcd
求L和R,
一道RMQ问题,明显树状数组和线段树什么的无法维护,但可以用莫队做
那么我们只需要考虑莫队的转移就好
若d1----dn为n的所有因数,
设d1----dn为gcd(a[i],a[j])的因数,
比如2,4,有cnt[1]=2,cnt[2]=2,cnt[4]=1,因为约数1,2出现两次,1、2为公约数,phi[1]+phi[2]=2=gcd(2,4)
若已知cnt[d]=x,x中任选2个,可以成为gcd(a[i],a[j])的公约数
所以我们统计约数个数就能计算出a[j]与a[1]----a[j-1]的gcd之和
同余
若,则称a,b模m同余
同余类
将相同的数归入一个集合,称为同余类
剩余系
m 的 m 个同余类称为完全剩余系
所有与 m 互质的同余类称为简化剩余系
简化剩余系乘法封闭,若 a,b 分别和 m 互质,则 a*b 也 和 m 互质
POJ2773 Happy 2006
求与n互质的第k小的数字
同理,
如题,若
以n为周期,求余,暴力第k小
欧拉定理
若正整数 a,n 互质,有
欧拉定理推论
若正整数a,p互质,则对于正整数b
当正整数 a,p 不一定互质时
UVA106992 Huge Mods
求
欧拉降幂板子题
HDU2837 Calculation
同上题
裴蜀定理
对于任意正整数a,b,存在一对整数x,y满足
扩展欧几里得算法
证明裴蜀定理的过程求出了 x 和 y,这个计算方法称为扩展欧几里得算法
代码求出了 gcd(a,b),并得到了 ax+by=gcd(a,b) 的一组特 解,x 和 y 需要以引用方式传入
//ax1+ by1= gcd(a,b);
//bx2 + (a mod b)y2 = gcd(b, a mod b);
//ax1 + by1 = bx2 + (a - [a / b] * b)y2 = ay2 + bx2 - [a / b] * by2;
//x1 = y2; y1 = x2 - [a / b] * y2;
LL gcd(LL a, LL b, LL &x, LL & y)
{
if (b == 0) {
x = 1, y = 0;
return a;
}
int q = gcd(b, a%b, y, x);
y -= a / b * x;
return q;
}
POJ2115 Looooops
求以下程序段的循环次数,其中变量为 k 位无符号整数
for (variable = A; variable != B; variable += C)
特解:
要
最小解:注意负数
POJ1061 青蛙的约会
简直和上一题一模一样
同余不等式
POJ3530 A Modular Arithmetic Challenge
求x使得
y越小-->x越小
两边求余
线性同余方程组
中国剩余定理
两两互质,,
是线性同余方程的一个解
对于任意n个整数,方程组
for (int i = 1; i <= n; i++) {
M[i] = M / m[i];
d = gcd(m[i], M[i], x, y);
ans += y * m[i] * M[i];
}
非互质线性同余方程组
以1、2两式为例
两边求余
,扩展欧几里得求解
将带会 式
且满足1,2两式
LL CRT() {
LL m1, m2, a1, a2, x, y, c;
m1 = m[1]; a1 = a[1];
bool flag = true;
for (int i = 2; i <= k; i++) {
m2 = m[i]; a2 = a[i];
c = exgcd(m1, m2, x, y);
if ((a2 - a1) % c)
flag = false;
x = (a2 - a1) / c * x;
y = m2 / c;
x = (x % y + y) % y;
a1 = x * m1 + a1;
m1 = (m1 * m2) / c;
}
c = exgcd(1, m1, x, y);
if (a1 % c) flag = false;
if (!flag)
return -1;
x = a1 / c * x;
y = m1 / c;
x = (x % y + y) % y;
return x;
}
POJ2891 Strange Way to Express Integers
板子题
GCD Table
高次同余方程
给定整数,求一个非负整数x,使得
BSGS算法
设,其中是步长,这里取,
方程变为
即
将存入哈希表,枚举i,计算是否存在于哈希表中,即可更新答案
int bsgs(int a, int b, int p) {
map<int, int> H;
H.clear();
b %= p;
int t = (int)sqrt(p) + 1;
for (int i = 0; i < t; i++) {
int val = (LL)b * quickpow(a, i, p) % p;
H[val] = i;
}
a = quickpow(a, t, p);
if (!a) return b ? -1 : 1;
for (int i = 0; i <= t; i++) {
int val = quickpow(a, i, p);
int j = H.find(val) == H.end() ? -1 : H[val];
if (j >= 0 && i * t >= j) return i * t - j;
}
return -1;
}
bzoj2242 [SDOI2011]计算器
板子题
原根与指标
知识点链接
例题代码
Prime Distance 代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const unsigned int max = 1 << 31;
const unsigned int maxn = 50000;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
bool vis[maxn + 5];
unsigned int prime[maxn + 5], cnt = 0;
void Init() { //预处理<=R的素数
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = true;
if (i % prime[j] == 0)break;
}
}
}
const unsigned int maxm = 1000000;
bool v[maxm + 10];
void interval_sieve(unsigned int l, unsigned int r) { //区间筛
unsigned int limit = sqrt(r * 1.0) + 1;
if (l == 1)v[0] = true;
for (int i = 0; i < cnt; i++) {
if (prime[i] > limit) break;
for (int j = (l - 1) / prime[i] + 1; j <= r / prime[i]; j++) {
if (j > 1) v[prime[i] * j - l] = true;
}
}
}
int main() {
Init();
unsigned int l, r;
while (cin >> l >> r) {
interval_sieve(l, r);
unsigned int p = 0, a = 0, b = 0, c = 0, d = 0, min = r - l + 1, max = 0;
while (v[p])p++;
bool flag = false;
for (unsigned int i = p + 1; i <= r - l; i++) {
if (!v[i]) {
flag = true;
if (i - p < min)
a = p, b = i, min = i - p;
if (i - p > max)
c = p, d = i, max = i - p;
p = i;
}
}
if (!flag)printf("There are no adjacent primes.\n");
else printf("%d,%d are closest, %d,%d are most distant.\n", a + l, b + l, c + l, d + l);
fill(v, v + r - l + 10, 0);
}
}
Counting Divisors代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long LL;
inline void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
const LL mod = 998244353;
const int maxn = 1000010;
bool vis[maxn + 5];
int prime[maxn + 5], cnt = 0;
void Prime() {
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i])prime[cnt++] = i;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = true;
if (prime[j] % i == 0)break;
}
}
}
LL k, num[maxn], d[maxn];
void slove(LL l, LL r) {
LL limit, g;
limit = sqrt(r * 1.0) + 1;
for (int i = 0; i < cnt; i++) {
if (prime[i] > limit)break;
LL s = (l + prime[i] - 1) / prime[i] * prime[i];
for (LL j = s; j <= r; j += prime[i]) { //用类似筛法的方法压缩时间
if (num[j - l] % prime[i] == 0) {
g = 0;
while (num[j - l] % prime[i] == 0) {
num[j - l] /= prime[i];
g++;
}
d[j - l] = d[j - l] * (k * g + 1) % mod;
}
}
}
}
int main() {
io(); Prime();
int t;cin >> t;
while (t--){
LL l, r;
cin >> l >> r >> k;
for (int i = 0; i <= r - l; i++)
num[i] = i + l, d[i] = 1;
slove(l, r);
LL ans = 0;
for (int i = 0; i <= r - l; i++) {
if (num[i] > 1) {
d[i] = d[i] * (k + 1) % mod;
}
ans += d[i]; ans %= mod;
}
cout << ans << '\n';
}
}
Combinations代码
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 50005;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
void Prime() {
prime[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i])prime[cnt++] = i;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = true;
if (prime[j] % i == 0)break;
}
}
}
int GetNum(int N, int x) {
int res = 0, m = x;
while (N >= m) {
res += N / m;
m *= x;
}
return res;
}
int main() {
io(); Prime();
int n, m;
while (cin >> n >> m) {
int k = n - m, ans = 0, limit = n;
for (int i = 0; i < cnt; i++) {
if (prime[i] > limit)break;
if (GetNum(n, prime[i]) - GetNum(k, prime[i]) - GetNum(m, prime[i]) > 0)
ans++;
}
printf("%d\n", ans);
}
}
余数之和代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
void io() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
// k mod i= k - k / i * i
int main() {
io();
LL ans, n, k, r;
cin >> n >> k;
ans = n * k;
n = min(n, k);
for (LL l = 1; l <= n; l = r + 1) {
LL u = k / l;
r = min(k / u, n);
ans -= (l + r) * (r - l + 1) / 2 * u;
}
cout << ans << '\n';
}
模积和代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
void io() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
LL mod = 19940417;
LL inv[8]; //求逆元
void init() {
inv[1] = 1;
for (LL i = 2; i <= 6; i++) {
inv[i] = (mod - mod / i) * (LL)1 * inv[mod % i] % mod;
}
}
// k mod i= k - k / i * i
LL GetNum(LL n) { //区间分块
LL ans = n * n % mod, r;
for (LL l = 1; l <= n; l = r + 1) {
LL u = n / l;
r = min(n / u, n);
ans = ans - (l + r) * (r - l + 1)/2 % mod * u % mod;
}
return ans % mod;
}
//sum(i,min(n,m))=(n*m-m*n/i*i-n*m/i*i+n/i*i*m/i*i)
int main() {
io(); init();
LL n, m, res;
cin >> n >> m;
res = GetNum(n) * GetNum(m) % mod;
if (n > m)swap(n, m);
LL cnt = n * m % mod * n % mod;
for (LL l = 1, r; l <= n; l = r + 1) {
r = min(n / (n / l), m / (m / l)); //选择较小的块移动
cnt += (n / l) * (m / l) % mod * ((r * (r + 1) % mod * (2 * r + 1) % mod * inv[6] % mod) - ((l - 1) * l % mod * (2 * l - 1) % mod * inv[6] % mod) + mod) % mod;
cnt -= m / l * n % mod * ((l + r) * (r - l + 1)/2 % mod); if (cnt < 0)cnt += mod;
cnt -= n / l * m % mod * ((l + r) * (r - l + 1)/2 % mod); if (cnt < 0)cnt += mod;
}
res -= cnt; res %= mod; if (res < 0)res+=mod;
cout << res << '\n';
}
斐波那契公约数代码
#include <iostream>
#include <cstdio>
using namespace std;
#pragma warning (disable:4996)
typedef long long int LL;
const LL mod = 1e8;
LL res[3][3] = { 0,0,0,0,1,1 }, r[3][3] = { 0,0,0,0,0,1,0,1,1 }, t[3][3];
LL gcd(LL a, LL b)
{
LL c;
while (c = a % b)
{
a = b;
b = c;
}
return b;
}
void mul(LL res[3][3], LL m[3][3], LL h)
{
for (int i = 1; i <= h; i++)
for (int j = 1; j <= 2; j++)
t[i][j] = (res[i][1] * m[1][j] % mod + res[i][2] * m[2][j] % mod) % mod;
for (int i = 1; i <= h; i++)
for (int j = 1; j <= 2; j++)
res[i][j] = t[i][j];
}
void quickmul(LL p)
{
while (p)
{
if (p & 1)
mul(res, r, 1);
mul(r, r, 2);
p >>= 1;
}
}
int main()
{
LL n, m;
scanf("%lld%lld", &n, &m);
LL cnt = gcd(n, m);
if (cnt == 1 || cnt == 2)
printf("1\n");
else
{
quickmul(gcd(n, m) - 2);
printf("%lld\n", res[1][2]);
}
}
GCD代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
typedef pair<int, int> pii;
typedef long long LL;
const int maxn = 100005;
map<int, LL> Map;
vector<pii> E[maxn];
int gcd(int a, int b) {
int c;
while (c=a%b){
a = b;
b = c;
}
return b;
}
int a[maxn], l[maxn], v[maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t, g = 0, n, q; cin >> t;
while (t--){
cout << "Case #" << ++g << ":\n";
cin >> n;
for (int i = 1; i <= n; i++)cin >> a[i];
int j;
for (int i = 1; i <= n; i++) {
for (v[i] = a[i], j = l[i] = i; j; j = l[j] - 1) {
v[j] = gcd(v[j], a[i]);
while (l[j] > 1 && gcd(a[i], v[l[j] - 1]) == gcd(a[i], v[j]))
l[j] = l[l[j] - 1];
E[i].push_back(pii(l[j], v[j]));
Map[v[j]] += LL(j - l[j] + 1);
}
}
cin >> q;
int L, R;
for (int i = 1; i <= q; i++) {
cin >> L >> R;
//cout << r << '\n';
for (int j = 0; j < E[R].size(); j++) {
if (L >= E[R][j].first) {
cout << E[R][j].second << ' ' << Map[E[R][j].second] << '\n';
break;
}
}
}
for (int i = 0; i <= n; i++) {
E[i].clear();
l[i] = v[i] = 0;
}
Map.clear();
}
}
Different GCD Subarray Query代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=100005;
int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
}
int n,q;
int tree[maxn];
inline int lowbit(int x) {
return x & -x;
}
void update(int x, int value) {
while (x <= n) {
tree[x] += value;
x += lowbit(x);
}
}
int query(int x) {
int ans = 0;
while (x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
int a[maxn],l[maxn],v[maxn];
map<int,int> Map;
void modify(int i) {
int j;
for (v[i] = a[i], j = l[i] = i; j; j = l[j] - 1) {
v[j] = gcd(v[j], a[i]);
while (l[j] > 1 && gcd(a[i], v[l[j] - 1]) == gcd(a[i], v[j]))
l[j] = l[l[j] - 1];
int p=Map[v[j]];
if(p==0) {
update(j,1);
} else if(p!=j) {
update(p,-1);
update(j,1);
}
Map[v[j]]=j;
}
}
struct node {
int left;
int right;
int ops;
friend bool operator <(node &a,node &b) {
return a.right<b.right;
}
} line[maxn];
int res[maxn];
int main() {
while(cin>>n>>q) {
for(int i=1; i<=n; i++)cin>>a[i];
for(int i=1; i<=q; i++) {
cin>>line[i].left>>line[i].right;
line[i].ops=i;
}
sort(line+1,line+1+q);
int next=1;
for(int i=1; i<=q; i++) {
while(next<=line[i].right) {
modify(next);
next++;
}
res[line[i].ops]=query(line[i].right)-query(line[i].left-1);
}
for(int i=1; i<=q; i++)
cout<<res[i]<<'\n';
fill(l,l+n+1,0);
fill(v,v+n+1,0);
fill(tree,tree+n+1,0);
Map.clear();
}
}
Farey Sequence代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1000005;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
void Phi() {
phi[1] = 1;
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
LL sum[maxn+5];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
Phi(); phi[1] = 0;
for (int i = 1; i <= maxn; i++)
sum[i] = sum[i - 1] + phi[i];
int n;
while (cin>>n&&n)
cout << sum[n] << '\n';
}
Visible Lattice Points代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1005;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
void Phi() {
phi[1] = 1;
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int sum[maxn + 5];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
Phi(); phi[1] = 0;
for (int i = 1; i <= maxn; i++)
sum[i] = sum[i - 1] + phi[i];
int n, x, g = 0; cin >> n;
while (n--) {
cin >> x;
cout << ++g << ' ' << x << ' ' << 2 * sum[x] + 3<<endl;
}
}
Longge's problem代码
//推导见数论博客
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 47000;
bool vis[maxn + 5];
int prime[maxn + 5], cnt = 0;
void Prime() {
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i;
for (int j = 0; j < cnt && i * prime[j] <= maxn; j++) {
vis[prime[j] * i] = true;
if (i % prime[j] == 0)break;
}
}
}
void slove(int n) {
int limit = sqrt(n * 1.0) + 1;
LL ans = 1;
int m, g;
for (int i = 0; i < cnt; i++) {
if (prime[i] > limit) break;
if (n % prime[i] == 0) {
m = n; g = 0;
while (n % prime[i] == 0) {
n /= prime[i];
g++;
}
ans = ans * (LL(m) / n / prime[i] * g * (prime[i] - 1) + m / n);
}
}
if (n > 1) ans = ans * (LL(2) * n - 1);
cout << ans << '\n';
}
int main() {
Prime();
int n;
while (cin >> n)
slove(n);
}
欧拉心算 代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 10000005;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
LL sum[maxn + 5];
void Phi() {
phi[1] = 1;
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
for (int i = 1; i <= maxn; i++)
sum[i] = sum[i - 1] + phi[i];
}
//Sum(phi[x])*2*Sum(phi[n/x])-1)
void slove(int n) {
LL ans = 0;
for (int l = 1, r; l <= n; l = r + 1) {
int u = n / l;
r = n / u;
ans += (sum[r] - sum[l - 1]) * (sum[u] * 2 - 1);
}
cout << ans << '\n';
}
int main() {
Phi();
int t, n;
cin >> t;
while (t--){
cin >> n;
slove(n);
}
}
gcd代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1000005;
const LL mod = 1e9 + 7;
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
LL sum[maxn + 5];
void Phi() {
phi[1] = 1;
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
for (int i = 1; i <= maxn; i++) {
sum[i] = sum[i - 1] + phi[i];
sum[i] %= mod;
}
}
LL quickpow(LL x,LL k) {
LL res = 1, m = x;
while(k){
if (k & 1) res *= m, res %= mod;
m *= m; m %= mod;
k >>= 1;
}
return res;
}
LL GetSum(LL x, LL l, LL r) {
LL inv = quickpow(x - 1, mod - 2);
LL ans = quickpow(x, l) * ((quickpow(x, r - l + 1) - 1 + mod) % mod) % mod * inv % mod;
ans = ans - (r - l + 1) + mod; ans %= mod;
return ans;
}
//Sum(x^k-1)*2*Sum(phi[n/x])-1)
void slove(LL x, LL n) {
LL ans = 0;
for (LL l = 1, r; l <= n; l = r + 1) {
LL u = n / l;
r = n / u;
ans += GetSum(x, l, r) * ((sum[u] * 2 - 1) % mod) % mod;
ans %= mod;
}
cout << ans << '\n';
}
int main() {
Phi();
int t, n, x;
cin >> t;
while (t--) {
cin >> x >> n;
if (x == 1) {
cout << "0\n";
continue;
}
slove(x, n);
}
}
Sum Of Gcd代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cmath>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
const int maxn = 20005;
int E[maxn + 5][233];
void Init() {
int cnt;
for (int i = 1; i < maxn; i++) {
cnt = 0;
for (int j = 1; j * j <= i; j++) {
if (i % j == 0) {
E[i][++cnt] = j;
if (j * j != i)
E[i][++cnt] = i / j;
}
}
E[i][0] = cnt;
}
}
bool vis[maxn + 5];
int prime[maxn + 5], cnt;
int phi[maxn + 5];
void Phi() {
phi[1] = 1;
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int a[maxn], ops[maxn];
LL res[maxn];
struct Node {
int id;
int left;
int right;
bool operator <(const Node& a)const{
if (ops[left] == ops[a.left])
return right < a.right;
return ops[left] < ops[a.left];
}
} q[maxn];
LL num[maxn];
int main() {
Init();
Phi();
int t, n, m, g = 0;
cin >> t;
while (t--) {
printf("Case #%d:\n", ++g);
scanf("%d", &n);
int Size = (int)sqrt(n * 1.0);
for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)ops[i] = i / Size;
scanf("%d", &m);
for (int i = 1; i <= m; i++){
scanf("%d%d", &q[i].left, &q[i].right);
q[i].id = i;
}
sort(q + 1, q + 1 + m);
int stdl = 1, stdr = 0;
LL ans = 0; int d;
for (int i = 1; i <= m; i++){
while (stdl > q[i].left){
stdl--;
for (int j = 1; j <= E[a[stdl]][0]; j++) {
d = E[a[stdl]][j];
num[d]++;
ans += (num[d] - 1) * phi[d];
}
}
while (stdr < q[i].right){
stdr++;
for (int j = 1; j <= E[a[stdr]][0]; j++) {
d = E[a[stdr]][j];
num[d]++;
ans += (num[d] - 1) * phi[d];
}
}
while (stdl < q[i].left){
for (int j = 1; j <= E[a[stdl]][0]; j++) {
d = E[a[stdl]][j];
ans -= (num[d] - 1) * phi[d];
num[d]--;
}
stdl++;
}
while (stdr > q[i].right){
for (int j = 1; j <= E[a[stdr]][0]; j++) {
d = E[a[stdr]][j];
ans -= (num[d] - 1) * phi[d];
num[d]--;
}
stdr--;
}
res[q[i].id] = ans;
}
for (int i = 1; i <= m; i++)
printf("%lld\n", res[i]);
memset(num, 0, sizeof(num));
}
}
Happy 2006代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
int Phi(int n) {
int ans = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) n /= i;
}
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int main() {
int n, k, phi;
while (~scanf("%d%d", &n, &k)) {
phi = Phi(n);
LL ans = LL(k - 1) / phi * n;
k %= phi;
if (k == 0)k = phi;
for (int i = 1; i <= n; i++) {
if (gcd(i, n) == 1)
k--;
if (k == 0) {
ans += LL(i);
break;
}
}
printf("%lld\n", ans);
}
}
Huge Mods代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long int LL;
int Phi(int n) {
int ans = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) n /= i;
}
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
int mod, k;
int a[30];
int quickpow(LL m, LL p, LL mod) {
LL res = 1, f1 = 0, f2 = 0;
while (p) {
if (p & 1) {
f1 |= (res * m >= mod || f2);
res *= m; res %= mod;
}
f2 |= (m * m >= mod);
m *= m; m %= mod;
p >>= 1;
}
return res + f1 * mod;
}
int slove(int x, int mod) {
if (x == k) return quickpow(a[x], 1, mod);
return quickpow(a[x], slove(x + 1, Phi(mod)), mod);
}
int main() {
int g = 0;
while (cin >> mod) {
if (mod == '#')break;
cin >> k;
for (int i = 1; i <= k; i++) cin >> a[i];
printf("Case #%d: %d\n", ++g, slove(1, mod) % mod);
}
}
Calculation代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long int LL;
LL Phi(LL n) {
LL ans = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) n /= i;
}
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
LL quickpow(LL m, LL p, LL mod) {
LL res = 1, f1 = 0, f2 = 0;
while (p) {
if (p & 1) {
f1 |= (res * m >= mod || f2);
res *= m; res %= mod;
}
f2 |= (m * m >= mod);
m *= m; m %= mod;
p >>= 1;
}
return res + f1 * mod;
}
LL n, m;
//f(n) = (n % 10) ^ f(n / 10)
LL slove(LL x, LL mod) {
if (x == 0) return 1;
return quickpow(x % 10, slove(x / 10, Phi(mod)), mod);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%lld%lld", &n, &m);
printf("%lld\n", slove(n, m) % m);
}
}
Looooops代码
#include <iostream>
#include <cstdio>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL in2[35];
void Init() {
for (int i = 1; i <= 34; i++)
in2[i] = LL(1) << i;
}
LL gcd(LL a, LL b, LL& x, LL& y)
{
if (b == 0) {
x = 1, y = 0;
return a;
}
int q = gcd(b, a % b, y, x);
y -= a / b * x;
return q;
}
int main() {
Init();
LL a, b, c, k;
while (cin >> a >> b >> c >> k && a + b + c + k) {
LL x, y;
LL d = gcd(c, in2[k], x, y);
if ((b - a) % d == 0) {
LL ans = x * (b - a) / d % in2[k];
printf("%lld\n", (ans % (in2[k] / d) + in2[k] / d) % (in2[k] / d));
}
else
printf("FOREVER\n");
}
}
青蛙的约会代码
#include <iostream>
#include <cstdio>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL in2[35];
void Init() {
for (int i = 1; i <= 34; i++)
in2[i] = LL(1) << i;
}
LL gcd(LL a, LL b, LL& x, LL& y)
{
if (b == 0) {
x = 1, y = 0;
return a;
}
int q = gcd(b, a % b, y, x);
y -= a / b * x;
return q;
}
int main() {
LL a, b, m, n, L, x, y;
cin >> a >> b >> m >> n >> L;
LL c = a - b;
a = n - m;
LL d = gcd(a, L, x, y);
if (c % d == 0) {
LL ans = x * c / d;
ans %= (L / d);
if (ans < 0)ans += L / d;
printf("%lld\n", ans);
}
else
printf("Impossible\n");
}
A Modular Arithmetic Challenge代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL slove(LL M, LL D, LL L, LL R) {
if (L > R || D == 0) return -1;
if (R / D * D >= L) return (L + D - 1) / D;
LL l = (-L) % D; if (l < 0) l += D;
LL r = (-R) % D; if (r < 0) r += D;
LL x = slove(D, M % D, r, l);
if (x == -1)return -1;
return (L + x * M + D - 1) / D;
}
int main() {
LL D, M, L, R, t;
cin >> t;
while (t--) {
cin >> M >> D >> L >> R;
R = min(M - 1, R);
cout << slove(M, D, L, R) << '\n';
}
}
Strange Way to Express Integers代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL gcd(LL a, LL b, LL& x, LL& y)
{
if (b == 0) {
x = 1;
y = 0;
return a;
}
LL q = gcd(b, a % b, y, x);
y -= a / b * x;
return q;
}
int main() {
LL k, m1, m2, a1, a2, x, y, c;
while (~scanf("%lld", &k)) {
scanf("%lld%lld", &m1, &a1);
bool flag = true;
k--;
while (k--) {
scanf("%lld%lld", &m2, &a2);
c = gcd(m1, m2, x, y);
if ((a2 - a1) % c) flag = false;
if(flag){
x = (a2 - a1) / c * x;
y = m2 / c;
x = (x % y + y) % y;
a1 = x * m1 + a1;
m1 = (m1 * m2) / c;
}
}
c = gcd(1, m1, x, y);
if (a1 % c) flag = false;
if(!flag) printf("-1\n");
else {
x = a1 / c * x;
y = m1 / c;
x = (x % y + y) % y;
printf("%lld\n", x);
}
}
}
GCD Table代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL gcd(LL a, LL b) {
return b == 0 ? a : gcd(b, a % b);
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
LL exgcd(LL a, LL b, LL& x, LL& y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
LL q = exgcd(b, a % b, y, x);
y -= a / b * x;
return q;
}
LL mul(LL x, LL p, LL mod) {
if (p < 0) x = -x, p = -p;
LL ret = 0;
for (; p; p >>= 1, x = (x + x) % mod) if (p & 1) ret = (ret + x) % mod;
return ret;
}
LL _x, _y, k;
LL m[10005], a[10005];
LL CRT() {
LL m1, m2, a1, a2, x, y, c;
m1 = m[1];
a1 = a[1];
bool flag = true;
for (int i = 2; i <= k; i++) {
m2 = m[i];
a2 = a[i];
c = exgcd(m1, m2, x, y);
if ((a2 - a1) % c)
flag = false;
y = m2 / c;
x = mul((a2 - a1) / c, x, y);
x = (x % y + y) % y;
a1 = x * m1 + a1;
m1 = (m1 * m2) / c;
}
c = exgcd(1, m1, x, y);
if (a1 % c) flag = false;
if (!flag)
return -1;
x = a1 / c * x;
y = m1 / c;
x = (x % y + y) % y;
return x == 0 ? y : x;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> _x >> _y >> k;
LL Lcm = 1;
for (int i = 1; i <= k; i++) {
cin >> m[i];
Lcm = lcm(Lcm, m[i]);
if (Lcm > _x) {
printf("NO\n");
return 0;
}
a[i] = ((m[i] - i + 1) % m[i] + m[i]) % m[i];
}
LL ans = CRT();
if (ans == -1 || ans + k - 1 > _y) {
printf("NO\n");
return 0;
}
for (int i = 1; i <= k; i++) {
if (gcd(Lcm, ans + i - 1) != m[i]) {
printf("NO\n");
return 0;
}
}
printf("YES\n");
}
[SDOI2011]计算器代码
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
LL quickpow(LL m, LL p, LL mod) {
LL res = 1;
while (p) {
if (p & 1) {
res *= m;
res %= mod;
}
m *= m;
m %= mod;
p >>= 1;
}
return res;
}
LL exgcd(LL a, LL b, LL& x, LL& y)
{
if (b == 0) {
x = 1, y = 0;
return a;
}
LL q = exgcd(b, a % b, y, x);
y -= a / b * x;
return q;
}
LL bsgs(LL a, LL b, LL p) {
map<LL, LL> H;
H.clear();
b %= p;
LL t = (LL)sqrt(p) + 1;
for (int i = 0; i < t; i++) {
LL val = (LL)b * quickpow(a, i, p) % p;
H[val] = i;
}
a = quickpow(a, t, p);
if (!a) return b ? -1 : 1;
for (int i = 0; i <= t; i++) {
LL val = quickpow(a, i, p);
LL j = H.find(val) == H.end() ? -1 : H[val];
if (j >= 0 && i * t >= j) return i * t - j;
}
return -1;
}
int main() {
LL t, k, _y, _z, _p, x, y;
while (~scanf("%lld%lld", &t, &k)) {
while (t--) {
scanf("%lld%lld%lld", &_y, &_z, &_p);
if (k == 1) {
printf("%lld\n",quickpow(_y, _z, _p) % _p);
}
else if (k == 2) {
LL a = _y, b = _p, d;
d = exgcd(a, b, x, y);
if (_z % d) {
printf("Orz, I cannot find x!\n");
continue;
}
x = _z / d * x;
y = _p / d;
x %= y; if (x < 0)x += y;
printf("%lld\n", x);
}
else {
LL ans = bsgs(_y, _z, _p);
if (ans == -1) {
printf("Orz, I cannot find x!\n");
continue;
}
printf("%lld\n", ans);
}
}
}
}