0w1

Yuki 377 背景パターン ( Burnside Lemma, Math )

No.377 背景パターン - yukicoder

題意:
H * W 格子的壁紙,每個格子有 K 種顏色中一種。這個壁紙由無窮左到無窮右不重疊貼滿,無窮下方至無窮下方也一樣。問牆壁的圖案有多少種,對 1e9 + 7 取模。兩個牆壁的圖案相同若且唯若同時存在相同一個 H * W 的圖案。

制約:
1 ≤ H, W, K ≤ 1e9

解法:
考慮用伯恩賽德定理,操作用 ( i, j ) 向量描述,其中 0 ≤ i < H and 0 ≤ j < W:
{ \displaystyle
{\large
\frac{1}{H\; \cdot \; W}\sum_{i\; =\; 0}^{H\; -\; 1}{\sum_{j\; =\; 0}^{W\; -\; 1}{\mbox{C}\left( \; i,\; j\;  \right)}}}
\\
{\large
\mbox{C}\left( \; i,\; j\;  \right):\; number\; of\; patterns\; that\; \mbox{re}main\; the\; same\; after\; \mbox{re}placement\; \left( \; i,\; j\;  \right)}
\\
{\large
\mbox{C}\left( \; i,\; j\;  \right)\; =\; K^{\; \frac{H\; \cdot \; W}{lcm\left( \; \frac{H}{gcd\left( \; i,\; H\;  \right)},\; \frac{W}{gcd\left( \; j,\; W\;  \right)} \right)}}}
\\
{\large
\sum_{i\; =\; 0}^{H\; -\; 1}{\sum_{j\; =\; 0}^{W\; -\; 1}{K^{\; \frac{H\; \cdot \; W}{lcm\left( \; \frac{H}{gcd\left( \; i,\; H\;  \right)},\; \frac{W}{gcd\left( \; j,\; W\;  \right)} \right)}}}}=\; \sum_{a\; |\; H}^{\; }{\sum_{b\; |\; W}^{\; }{K^{\frac{H\; \cdot \; W}{lcm\left( \; \frac{H}{a},\; \frac{W}{b} \right)}}\; \cdot \; f\left( \; H,\; a\;  \right)\; \cdot \; f\left( \; W,\; b\;  \right)}}}
\\
{\large
f\left( \; N,\; x\;  \right)\; =\; \sum_{i\; =\; 0}^{N\; -\; 1}{1\; [ \; gcd\left( \; N,\; i\;  \right)\; =\; x\;  ]\; =\; ϕ\left( \; \frac{N}{x} \right)}}
}

時間 / 空間複雜度:
O( max( H, W )^(1/3) ^ 3 lg ( H * W ) )

from itertools import product
from functools import reduce

MOD = int( 1e9 ) + 7

H, W, K = map( int, input().split() )

def gcd( a, b ):
  return a if b == 0 else gcd( b, a % b )

def is_prime( n ):
  return 1 < n and all( n % i for i in range( 2, int( n ** 0.5 ) + 1 ) )

def factors( n ):
  return [ i for i in range( 1, int( n ** 0.5 ) + 1 ) if n % i == 0 ] + [ n // i for i in range( 1, int( n ** 0.5 ) + 1 ) if i * i != n and n % i == 0 ]

hf, wf = factors( H ), factors( W )
hp, wp = [ v for v in hf if is_prime( v ) ], [ v for v in wf if is_prime( v ) ]
phi = { x : reduce( lambda a, b: a // b * ( b - 1 ), [ x ] + [ p for p in ( hp if H % x == 0 else wp ) if x % p == 0 ] ) for x in hf + wf }

ans = sum( pow( K, H // a * W // b * gcd( a, b ), MOD ) * phi[ a ] * phi[ b ] for a, b in product( hf, wf ) ) * pow( H * W, MOD - 2, MOD ) % MOD
print( ans )