数学基础问题
Again Prime? No time.
The Super Powers
不妨设一个超级幂的唯一分解,对于某质因子 p p p 有
p e = p s 1 s 2 ⋯ s m e = s 1 s 2 ⋯ s m \begin{aligned}
p^e &= p^{s_1s_2\cdots s_m} \\
e &= s_1s_2\cdots s_m
\end{aligned}
p e e = p s 1 s 2 ⋯ s m = s 1 s 2 ⋯ s m
不难想到,如果一个数是超级幂,满足
{ e 是合数,且 e > 4 枚举底数 x ∈ [ 2 → 2 64 − 1 ] , e ⩽ ⌈ 64 ⋅ log ( 2 ) log ( x ) ⌉ − 1 \begin{cases}
e \ \text{是合数,且} \ e > 4 \\
\text{枚举底数} \ x \in [2 \to 2^{64}-1], e \leqslant \left\lceil \frac{64 \cdot \log(2)}{\log(x)} \right\rceil - 1
\end{cases}
{ e 是合数,且 e > 4 枚举底数 x ∈ [ 2 → 2 6 4 − 1 ] , e ⩽ ⌈ l o g ( x ) 6 4 ⋅ l o g ( 2 ) ⌉ − 1
暴力法即可解决
for ∀ x ∈ [ 2 ⋯ ] \textbf{for} \ \forall x \in [2 \cdots ] for ∀ x ∈ [ 2 ⋯ ] 枚举底数 x , e ⩽ ⌈ 64 ⋅ log ( 2 ) log ( x ) ⌉ − 1 x, \quad e \leqslant \left\lceil \frac{64 \cdot \log(2)}{\log(x)} \right\rceil - 1 x , e ⩽ ⌈ l o g ( x ) 6 4 ⋅ l o g ( 2 ) ⌉ − 1
r e s ← 1 for ∀ i ∈ [ 1 → e ] res \leftarrow 1 \quad \textbf{for} \ \forall i \in [1 \to e] r e s ← 1 for ∀ i ∈ [ 1 → e ] 枚举指数 i i i
r e s ← r e s × ∏ x ⇔ r e s = r e s ⋅ x i \quad res \leftarrow res \times \prod x \ \Leftrightarrow \ res = res \cdot x^i r e s ← r e s × ∏ x ⇔ r e s = r e s ⋅ x i
if i 为合数 , x i 是 super power , r e s → ans { ⋯ } \textbf{if} \ i \ \text{为合数}, \quad x^{i} \ \text{是 super power}, \ res \to \text{ans}\{\cdots \} if i 为合数 , x i 是 super power , r e s → ans { ⋯ }
说明,在算法中我们只需要从小到大枚举底数 x x x ,然后取幂指 i i i 为合数即可,如果 x x x 可以进行分解
因为是从小到大枚举的,x x x 的因数一定在 x x x 之前被检查到了,并不会漏解
Teams
根据组合原理,所求的方案是
S ( n ) = ∑ k = 1 n ( n k ) ( k 1 ) = ∑ k = 1 n k ⋅ ( n k ) S ( n ) = 1 ( n 1 ) + 2 ( n 2 ) + ⋯ ( n − 1 ) ( n n − 1 ) + n ( n n ) S ( n ) = n ( n n ) + ( n − 1 ) ( n n − 1 ) + ( n − 2 ) ( n n − 2 ) ⋯ + 1 ( n 1 ) \begin{aligned}
S(n) &= \sum_{k=1}^{n} \binom{n}{k} \binom{k}{1} = \sum_{k=1}^{n} k \cdot \binom{n}{k} \\
S(n) &= 1\binom{n}{1} + 2\binom{n}{2} + \cdots (n-1) \binom{n}{n-1} + n \binom{n}{n} \\
S(n) = n\binom{n}{n} + &(n-1)\binom{n}{n-1} + (n-2)\binom{n}{n-2} \cdots + 1\binom{n}{1}
\end{aligned}
S ( n ) S ( n ) S ( n ) = n ( n n ) + = k = 1 ∑ n ( k n ) ( 1 k ) = k = 1 ∑ n k ⋅ ( k n ) = 1 ( 1 n ) + 2 ( 2 n ) + ⋯ ( n − 1 ) ( n − 1 n ) + n ( n n ) ( n − 1 ) ( n − 1 n ) + ( n − 2 ) ( n − 2 n ) ⋯ + 1 ( 1 n )
从而可以推出
2 S ( n ) = n ⋅ 2 n ⇒ S ( n ) = n ⋅ 2 n − 1 2S(n) = n \cdot 2^{n} \Rightarrow S(n) = n \cdot 2^{n-1}
2 S ( n ) = n ⋅ 2 n ⇒ S ( n ) = n ⋅ 2 n − 1
唯一分解定理
LCM Cardinality
其实条件可以写成
{ a ⋅ b = n ⋅ gcd ( a , b ) gcd ( a , b ) ∣ n \begin{cases}
&a \cdot b = n \cdot \text{gcd}(a, b) \\
&\text{gcd}(a, b) \mid n
\end{cases}
{ a ⋅ b = n ⋅ gcd ( a , b ) gcd ( a , b ) ∣ n
很容易想到应该对 n n n 进行素因子分解
对 n n n 进行素因子分解n = p 1 s 1 p 2 s 2 ⋯ p m s m a = p 1 a 1 p 2 a 2 ⋯ p m s m b = p 1 b 1 p 2 b 2 ⋯ p m s m \begin{aligned}
n &= p_1^{s_1}p_2^{s_2} \cdots p_m^{s_m} \\
a &= p_1^{a_1}p_2^{a_2} \cdots p_m^{s_m} \\
b &= p_1^{b_1}p_2^{b_2} \cdots p_m^{s_m}
\end{aligned}
n a b = p 1 s 1 p 2 s 2 ⋯ p m s m = p 1 a 1 p 2 a 2 ⋯ p m s m = p 1 b 1 p 2 b 2 ⋯ p m s m
原问题等价于{ max ( a i , b i ) = s i s i 中有多少种无序 ( a i , b i ) 组合 \begin{cases}
\max(a_i, b_i) = s_i \\
s_i \text{中有多少种无序} (a_i, b_i) 组合
\end{cases}
{ max ( a i , b i ) = s i s i 中有多少种无序 ( a i , b i ) 组 合
先从 ( a i , b i ) (a_i, b_i) ( a i , b i ) 中任选一个令其等于 s i s_i s i ,有 ( 2 1 ) 2 \choose 1 ( 1 2 ) 种
剩下的元素从 [ 0 , s i − 1 ] [0, s_i-1] [ 0 , s i − 1 ] 中选,有 s i s_i s i 种,一共有 ( 2 1 ) ⋅ s i = 2 s i \binom{2}{1} \cdot s_i = 2s_i ( 1 2 ) ⋅ s i = 2 s i 种
另外考虑到 a i = b i = s i a_i = b_i = s_i a i = b i = s i 这一种情况,因为是 ( a i , b i ) (a_i, b_i) ( a i , b i ) 无序数组,所以 ( s i , s i ) (s_i, s_i) ( s i , s i ) 算作 1 1 1 种
∀ p i \forall \ p_i ∀ p i ,一共有 2 s i + 1 2s_i + 1 2 s i + 1 种选择
∏ i ( 2 s i + 1 ) 2 \frac{\prod_i (2s_i + 1)}{2}
2 ∏ i ( 2 s i + 1 )
但注意 ∏ ( 2 s i + 1 ) \prod(2s_i + 1) ∏ ( 2 s i + 1 ) 是奇数,此时 ∏ ( 2 s i + 1 ) \prod(2s_i+1) ∏ ( 2 s i + 1 ) 的结果中包含 ( n , n ) (n, n) ( n , n ) 这一组
要 + 1 +1 + 1 后除以 2 2 2 才是答案a n s = ⌈ ∏ i ( 2 s i + 1 ) + 1 2 ⌉ = ⌊ ∏ i ( 2 s i + 1 ) 2 ⌋ + 1 ans = \left\lceil \frac{\prod_i (2s_i + 1) + 1}{2} \right\rceil = \left\lfloor \frac{\prod_i (2s_i+1)}{2} \right\rfloor + 1
a n s = ⌈ 2 ∏ i ( 2 s i + 1 ) + 1 ⌉ = ⌊ 2 ∏ i ( 2 s i + 1 ) ⌋ + 1
UVA10791
同余与剩余类
任意整数 a m o d p a \bmod p a m o d p ,可以根据余数组成 p p p 个类,分别为
{ 0 } , { 1 } , ⋯ , { p − 1 } \{0\}, \{1\}, \cdots , \{p-1\}
{ 0 } , { 1 } , ⋯ , { p − 1 }
于是很多同余问题就转换成剩余类计数问题,比如我们可以用 s { 0 } s_{\{0\}} s { 0 } 表示剩余类 { 0 } \{0\} { 0 } 的个数
剩余类的个数表示为
s { 0 } , s { 1 } , ⋯ , s { p − 1 } s_{\{0\}}, s_{\{1\}}, \cdots , s_{\{p-1\}}
s { 0 } , s { 1 } , ⋯ , s { p − 1 }
如果一个 B B B 位数能够被 p p p 整除,那么这个数每个数位的和 ∑ i \sum_{i} ∑ i 也能够被 p p p 整除
可以遍历每个数位 for ∀ i ∈ [ 0 , B ) \textbf{for} \ \forall i \in [0, B) for ∀ i ∈ [ 0 , B ) ,统计出
s { 0 } , s { 1 } , ⋯ , s { p − 1 } ∑ i ≡ 1 s { 1 } + 2 s { 2 } + ⋯ + ( p − 1 ) s { p − 1 } ( m o d p ) \begin{gathered}
s_{\{0\}}, s_{\{1\}}, \cdots , s_{\{p-1\}} \\
\sum_{i} \equiv 1s_{\{1\}} + 2s_{\{2\}} + \cdots + (p-1)s_{\{p-1\}} (\bmod p)
\end{gathered}
s { 0 } , s { 1 } , ⋯ , s { p − 1 } i ∑ ≡ 1 s { 1 } + 2 s { 2 } + ⋯ + ( p − 1 ) s { p − 1 } ( m o d p )
UVA11489
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 int s[4]; string str; void solve () { for (auto x : str) s[x % 3]++; int mo = 0; for (int i = 0; i <= 2; i++) mo += i * s[i]; mo %= 3; if (mo == 0) { string res; s[0] % 2 ? res = "S" : res = "T" ; printf ("%s\n" , res.c_str()); } else { if (s[mo] == 0) printf ("T\n" ); else { string res; s[0] % 2 ? res = "T" : res = "S" ; printf ("%s\n" , res.c_str()); } } } int main () { freopen("input.txt" , "r" , stdin); int T; cin >> T; int kase = 0; while (T--) { printf ("Case %d: " , ++kase); memset(s, 0, sizeof s); cin >> str; solve(); } }
组合计数基础
重复元素的全排列方案数
定理 n n n 个元素,分为 m m m 组,其中本组元素全部相同,不同组元素不同,并且第 i i i 组有 p i p_i p i 个
总的排列数为
n ! ∏ k = 1 m p k ! \frac{n!}{\prod_{k=1}^{m} p_k !}
∏ k = 1 m p k ! n !
Add Again
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 const int maxn = 15; const ll one[13] = { 0, 1, 11, 111, 1111, 11111, 111111, 1111111, 11111111, 111111111, 1111111111, 11111111111, 111111111111 }; int n; ll fac[maxn]; int cnt[maxn]; void prework () { fac[0] = fac[1] = 1; for (int i = 2; i <= 12; i++) { fac[i] = fac[i-1] * (ll)i; } } int main () { freopen("input.txt" , "r" , stdin); prework(); while (scanf("%d" , &n) == 1 && n) { memset(cnt, 0, sizeof cnt); int sum = 0; for (int i = 0; i < n; i++) { int x; scanf("%d" , &x); sum += x, cnt[x]++; } ll res = (ll)sum * fac[n-1]; for (int i = 0; i <= 9; i++) res /= fac[cnt[i]]; printf ("%lld\n" , res * one[n]); } }
回文串计数举例
UVA12050
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 const int N = 20; ll cnt[N]; int C; void prework () { cnt[1] = 9, cnt[2] = 9; for (int i = 3; i < N; i++) { if (i & 1) cnt[i] = cnt[i-2] * 10; else cnt[i] = cnt[i-1]; } } void solve () { // i len, C th int i = 1; for (; i < N; i++) { if (cnt[i] < C) C -= cnt[i]; else break ; } C--; string str(i, '0' ); int k = i/2; while (C) { str[k++] = '0' + C % 10; C /= 10; } str[i-1]++; for (int j = 0; j < i/2; j++) { str[j] = str[i-1-j]; } printf ("%s\n" , str.c_str()); } int main () { freopen("input.txt" , "r" , stdin); prework(); // for (int i = 1; i < N; i++) debug(cnt[i]); while (scanf("%d" , &C) == 1 && C) { solve(); } }