【poj2154】Color Polya定理+欧拉函数
T 组询问,用 n 种颜色去染 n 个点的环,旋转后相同视为同构。求不同构的环的个数模 p 的结果。 T≤3500,n≤109,p≤30000 。
题解
Polya定理+欧拉函数
根据 poj2409 中得到的结论,答案为:
n∑i=1ngcd
由于 n 有 10^9 之大,因此考虑优化这个式子。
枚举 \gcd(i,n) ,则有:
Ans=\sum\limits_{d|n}n^{d-1}\sum\limits_{j=1}^{\frac nd}[\gcd(j·d,n)==d]\\\ \ \ \ \ \ \ =\sum\limits_{d|n}n^{d-1}\sum\limits_{j=1}^{\frac nd}[\gcd(j,\frac nd)==1]\\\ \ \ \ \ \ \ =\sum\limits_{d|n}n^{d-1}\varphi(\frac nd)\\\ \ \ \ \ \ \ =\sum\limits_{k|n}n^{\frac nk-1}\varphi(k)
此时 k 是 n 的约数,总个数不会超过 O(\sqrt n) 个。但是直接枚举约数的话难以快速算出 \varphi 值。
考虑将 n 分解质因数,设 n=\prod\limits_{i=1}^mp_i^{a_i} ,那么我们dfs枚举 k=\prod\limits_{i=1}^mp_i^{b_i}\ (0\le b_i\le a_i) ,由于 \varphi 是积性函数,所以在枚举的过程中就可以顺便求出 \varphi 值 ,再与 n^{\frac nk-1} 作乘积累加到答案中即可。这样能够不重不漏地枚举到 n 的所有约数并统计答案。
时间复杂度 O(T\sqrt n\log n) ,由于这个根号是远远不满的,因此可以过。
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 46 47 | #include <cstdio> int a[40] , c[40] , tot , n , p , ans; inline int pow ( int x , int y) { int ans = 1; while (y) { if (y & 1) ans = ans * x % p; x = x * x % p , y >>= 1; } return ans; } void dfs( int x , int d , int v) { if (x > tot) { ans = (ans + pow (n % p , n / d - 1) * (v % p)) % p; return ; } int i; dfs(x + 1 , d , v); d *= a[x] , v *= a[x] - 1; for (i = 1 ; i <= c[x] ; i ++ , d *= a[x] , v *= a[x]) dfs(x + 1 , d , v); } int main() { int T , i , x; scanf ( "%d" , &T); while (T -- ) { scanf ( "%d%d" , &n , &p); tot = 0 , x = n; for (i = 2 ; i * i <= x ; i ++ ) { if (!(x % i)) { a[++tot] = i , c[tot] = 0; while (!(x % i)) x /= i , c[tot] ++ ; } } if (x != 1) a[++tot] = x , c[tot] = 1; ans = 0 , dfs(1 , 1 , 1); printf ( "%d\n" , ans); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步