题意:给定
1
≤
a
<
m
≤
1
0
10
1\leq a
思路:推一下式子:
容易知道 k = gcd ( a , m ) k=\gcd(a,m) k=gcd(a,m) 一定是 m m m 的因子。我们先计算出 a + x a+x a+x 的范围内是 k k k 的倍数的左右边界,倍数范围即为 [ l , r ] = [ ⌈ a k ⌉ , ⌊ a + m − 1 k ⌋ ] [l,r]=[\left \lceil \frac a k \right \rceil,\left \lfloor \frac{a+m-1} k \right \rfloor] [l,r]=[⌈ka⌉,⌊ka+m−1⌋] 。那么 ∑ x = 0 m − 1 [ gcd ( a , m ) = gcd ( a + x , m ) ] = ∑ i = l r [ gcd ( i , m k ) = 1 ] \sum_{x=0}^{m-1}{[\gcd(a,m)=\gcd(a+x,m)]}=\sum_{i=l}^r{[\gcd(i,\frac m k)=1]} ∑x=0m−1[gcd(a,m)=gcd(a+x,m)]=∑i=lr[gcd(i,km)=1] ,那么问题转化为求 l ∼ r l\sim r l∼r 中有多少个数与 m k \frac m k km 互质。
一个经典的问题就是求 1 ∼ n 1\sim n 1∼n 有多少个数与 m m m 互质,方法为:对 m m m 分解质因子,然后二进制枚举容斥计算,时间复杂度 O ( n + 2 11 ) O(\sqrt n+2^{11}) O(n+211) ,这里的 11 11 11 是指 1 0 10 10^{10} 1010 内的数字最多有 11 11 11 个质因子。
总结了一些关于 gcd \gcd gcd 的性质:
gcd
(
a
,
b
)
=
gcd
(
a
,
a
+
b
)
\gcd(a,b)=\gcd(a,a+b)
gcd(a,b)=gcd(a,a+b) ,序列的前缀和序列或差分序列的
gcd
\gcd
gcd 相等
gcd
(
k
×
a
,
k
×
b
)
=
k
×
gcd
(
a
,
b
)
\gcd(k\times a,k\times b)=k \times \gcd(a,b)
gcd(k×a,k×b)=k×gcd(a,b)
gcd
(
a
,
b
)
=
p
×
gcd
(
a
p
,
b
p
)
\gcd(a,b)=p\times \gcd(\frac a p,\frac b p)
gcd(a,b)=p×gcd(pa,pb) ,要保证
p
p
p 是
a
,
b
a,b
a,b 的因子
gcd
(
a
k
,
b
k
)
=
gcd
k
(
a
,
b
)
\gcd(a^k,b^k)=\gcd^k(a,b)
gcd(ak,bk)=gcdk(a,b)
c
∣
a
×
b
⇒
c
gcd
(
b
,
c
)
∣
a
c|a\times b\Rightarrow \frac c{\gcd(b,c)}|a
c∣a×b⇒gcd(b,c)c∣a
模板:
LL cal(LL n, LL m){ // numbers of i in 1 ~ n : gcd(i, m) == 1
vector<LL> vec;
for(LL i = 2; i * i <= m; i ++ ){
if(m % i == 0){
while(m % i == 0) m /= i;
vec.pb(i);
}
}
if(m > 1) vec.pb(m);
LL res = 0;
for(int bit = 1; bit < 1 << vec.size(); bit ++ ){
LL mul = 1;
rep(i, 0, (int)vec.size() - 1) if(bit >> i & 1) mul *= vec[i];
if(__builtin_popcount(bit) & 1) res += n / mul;
else res -= n / mul;
}
return n - res;
}
AC代码:http://oj.daimayuan.top/submission/321288
题意:给定正整数 N N N , 求出 1 ∼ N − 1 1∼N−1 1∼N−1 中所有与 N N N 互质的数构成的序列 的中位数.
我们定义 : 一个长度为 K K K 的序列的中位数是序列中第 ⌊ K + 1 2 ⌋ ⌊\frac{K+1}2⌋ ⌊2K+1⌋ 大的数字. 且两个正整数 a a a 与 b b b 互质当且仅当 gcd ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1 。
思路:打表可以发现规律。证明的话: gcd ( i , x ) = gcd ( x − i , x ) \gcd(i,x)=\gcd(x-i,x) gcd(i,x)=gcd(x−i,x) ,大概就是这个式子。
AC代码:http://oj.daimayuan.top/submission/322050
题意: 1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1≤n≤105
思路:树状数组优化 DP 。
我们按照下标枚举 a a a 里的元素,去枚举 b b b 里对应的元素。我们先定义 d p ( i , j ) dp(i,j) dp(i,j) 表示 a a a 前 i i i 个元素和 b b b 前 j j j 个元素的最大匹配,转移方程为 d p ( i , j ) = max 1 ≤ i ′ < i , 1 ≤ j ′ < j d p ( i ′ , j ′ ) + 1 dp(i,j)=\max_{1\leq i'dp(i,j)=max1≤i′<i,1≤j′<jdp(i′,j′)+1 。
可以发现这是个二维偏序,第一维能被优化。对于和当前枚举的 i i i 对应的 j j j ,转移方程为 d p ( j ) = max ( d p ′ ( j ) , max k = 1 j − 1 d p ′ ( k ) + 1 ) dp(j)=\max(dp'(j),\max_{k=1}^{j-1}dp'(k)+1) dp(j)=max(dp′(j),maxk=1j−1dp′(k)+1) ,用树状数组维护第二维的前缀最值即可即可。