【poj2154】Color Polya定理+欧拉函数

题目描述

$T$ 组询问,用 $n$ 种颜色去染 $n$ 个点的环,旋转后相同视为同构。求不同构的环的个数模 $p$ 的结果。 $T\le 3500,n\le 10^9,p\le 30000$ 。



题解

Polya定理+欧拉函数

根据 poj2409 中得到的结论,答案为:

$\frac{\sum\limits_{i=1}^nn^{\gcd(i,n)}}n=\sum\limits_{i=1}^nn^{\gcd(i,n)-1}$

由于 $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)$ ,由于这个根号是远远不满的,因此可以过。

#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;
}

原文地址:https://www.cnblogs.com/GXZlegend/p/8297293.html

时间: 2024-08-05 00:52:02

【poj2154】Color Polya定理+欧拉函数的相关文章

Polya 定理入门[Burnside引理,Polya定理,欧拉函数]

$这篇blog重点讨论Polya的应用, 更详细的证明请百度 .$ ___ $Burnside引理$ $$L=\frac{1}{|G|}\sum_{i=1}^{|G|}D(a_i)$$ $L$: 本质不同的方案数. $G$: 置换群集合. $a_i$: 置换群中的第 $i$ 个置换. $D(a_i)$: 进行 $a_i$ 这个置换, 状态不会变化的方案 数量. 该引理与下方内容没有太大关系, 可以暂时忽略. ___ $Problem$ 链接 有 $N$ 个石子围成一圈, 使用 $M$ 种颜色染色

poj2054Color polya定理+欧拉函数优化

没想到贱贱的数据居然是错的..搞得我调了一中午+晚上一小时(哦不d飞LJH掉RP毕竟他是BUFF)结果重判就对了五次.. 回归正题,这题傻子都看得出是polya定理(如果你不是傻子就看这里),还没有翻转,就一个旋转,结果我就欢快的打完交上去了.傻子都知道会TLE,n<=1e9啊,O(n)都原地爆炸,那怎么办...一脸懵逼(然后就膜题解了) 可以发现,这题公式就是sigma(gcd(k,n))(k=1~n),然后该怎么优化呢,我(??)发现gcd(k,n)里面肯定有一些k和n的gcd是相同的,那我

Luogu4980 【模板】Polya定理(Polya定理+欧拉函数)

对于置换0→i,1→i+1--,其中包含0的循环的元素个数显然是n/gcd(i,n),由对称性,循环节个数即为gcd(i,n). 那么要求的即为Σngcd(i,n)/n(i=0~n-1,也即1~n).考虑枚举gcd.显然gcd(i,n)=x在该范围内解的个数是φ(n/x).分解一下质因数即可. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<c

poj 2154 Color(polya计数 + 欧拉函数优化)

http://poj.org/problem?id=2154 大致题意:由n个珠子,n种颜色,组成一个项链.要求不同的项链数目,旋转后一样的属于同一种,结果模p. n个珠子应该有n种旋转置换,每种置换的循环个数为gcd(i,n).如果直接枚举i,显然不行.但是我们可以缩小枚举的数目.改为枚举每个循环节的长度L,那么相应的循环节数是n/L.所以我们只需求出每个L有多少个i满足gcd(i,n)= n/L,就得到了循环节数为n/L的个数.重点就是求出这样的i的个数. 令cnt = gcd(i,n) =

POJ2154 Color polya定理+欧拉定理

由于这是第一天去实现polya题,所以由易到难,先来个铺垫题(假设读者是看过课件的,不然可能会对有些“显然”的地方会看不懂): POJ1286 Necklace of Beads :有三种颜色,问可以翻转,可以旋转的染色方案数,n<24. 1,n比较小,恶意的揣测出题人很有可能出超级多组数据,所以先打表. 2,考虑旋转: for(i=0;i<n;i++) sum+=pow(n,gcd(n,i)); 3,考虑翻转: if(n&1) sum+=n*pow(3,n/2+1) ; else {

poj2409 &amp; 2154 polya计数+欧拉函数优化

这两个题都是项链珠子的染色问题 也是polya定理的最基本和最经典的应用之一 题目大意: 用m种颜色染n个珠子构成的项链,问最终形成的等价类有多少种 项链是一个环.通过旋转或者镜像对称都可以得到置换 旋转可以旋转 i=[1,n]次..画图可以看出循环节有gcd(n,i)个 镜像对称的置换画个图也是很容易找的 然后通过polya定理就可以容易的求出等价类的种数了 2409就是这样一个裸题,以下为ac代码 #include <iostream> #include <stdio.h> #

POJ2154 Color(Polya定理)

Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11654   Accepted: 3756 Description Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of the nec

费马小定理,欧拉函数

在证明这些定理之前先证明一个有意思的定理. 对于0 mod m,n mod m , 2n mod m, 3n mod m, 4n mod m... (m-1)n mod m 对应解集序列 一定有 m/d份 0 d 2d 3d..m-d. (不一定按照顺序) 这样的解. 其中d = gcd(n,m) 具体点:n=8,m=12.  d = gcd(n,m)=4 对于 0 mod 12,8 mod 12,16 mod 12,24 mod 12,32 mod 12,40 mod 12...88 mod

【SPOJ419】Transposing is Fun P&#243;lya定理+欧拉函数

[SPOJ419]Transposing is Fun 题意:给你一个$2^a\times2^b$的矩阵,将$1...n$中的数依次从左到右,从上往下填到矩阵里,再把矩阵转置,然后把所有数从左到右,从上往下拿出来得到一个新的排列$A$.你现在每次可以交换两个数,问你从$1...n$变成排列$A$最少要进行多少次操作. 询问次数$\le400000,a+b\le 10^6$ 题解:首先我们可以找到所有的循环节,如果一个循环节中有$x$个数,需要交换$x-1$次.所以我们只需要求出循环节的个数$k$