zoukankan      html  css  js  c++  java
  • P4980 【模板】Polya定理

    (color{#0066ff}{ 题目描述 })

    给定一个(n)个点,(n)条边的环,有(n)种颜色,给每个顶点染色,问有多少种本质不同的染色方案,答案对(10^9+7)取模

    注意本题的本质不同,定义为:只需要不能通过旋转与别的染色方案相同

    (color{#0066ff}{输入格式})

    第一行输入一个(t),表示有(t)组数据

    第二行开始,一共(t)行,每行一个整数(n),意思如题所示。

    (color{#0066ff}{输出格式})

    (t)行,每行一个数字,表示染色方案数对(10^9+7)取模后的结果

    (color{#0066ff}{输入样例})

    5
    1 
    2 
    3 
    4 
    5 
    

    (color{#0066ff}{输出样例})

    1
    3
    11
    70
    629
    

    (color{#0066ff}{数据范围与提示})

    (n leq 10^9)(,t leq 10^3)

    (color{#0066ff}{ 题解 })

    前置知识

    1、置换

    就是将元素的对应以表格形式来表示

    标准形式为

    (left(egin{aligned}1 && 2 && 3 && 4 && dots && n \ a_1 && a_2 && a_3 && a_4 && dots && a_nend{aligned} ight))

    其中(a_1dots a_n)(1-n)的一个排列

    相当于经过变换,原来1的位置到了(a_1),2的位置到了(a_2)。。。

    根据题意,本质不同即为旋转

    于是单次置换为

    (left(egin{aligned}1 && 2 && 3 && 4 && dots && n \ 2 && 3 && 4 && 5 && dots && 1end{aligned} ight))

    二次置换为

    (left(egin{aligned}1 && 2 && 3 && 4 && dots && n \ 3 && 4 && 5 && 6 && dots && 2end{aligned} ight))

    2、Burnside引理

    对于每个置换f,我们定义C(f)为在置换f下保持不变的方案数。

    则有: 本质不同的方案数为C(f)的平均数。

    (ans=frac{1}{left | G ight |} sum _{f in G})

    3、Polya定理

    (egin{aligned}ans=frac 1 n sum_{i=1}^n m^{x_i}end{aligned})

    其中,n为置换长度,m是染色种类,(x_i)是i次置换的循环个数

    循环个数是啥呢

    比如上面的一次置换,个数为1,(1 o2 o3 o4 o5 o1)

    比如长度为6的三次置换,个数为3

    (left(egin{aligned}1 && 2 && 3 && 4 && 5 && 6\ 4 && 5 && 6 && 1 && 2 && 3end{aligned} ight))

    第一个循环(1 o4 o1)

    第二个循环(2 o5 o2)

    第三个循环(3 o6 o3)

    不难发现,(x_i=gcd(i,n))

    于是改为枚举n的因子

    (egin{aligned}ans=frac 1 n sum_{i=1}^n m^{gcd(i,n)}end{aligned})

    (egin{aligned}ans=frac 1 n sum_{d|n}^n varphi(frac n d)* m^{d}end{aligned})

    表面上这东西的复杂度是(O(T*(sqrt n)^2)=O(Tn))

    但实际上,求(varphi)的根号只会被调用log次

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int mod = 1e9 + 7;
    LL ksm(LL x, LL y) {
    	LL re = 1LL;
    	while(y) {
    		if(y & 1) re = re * x % mod;
    		x = x * x % mod;
    		y >>= 1;
    	}
    	return re;
    }
    LL getphi(LL n) {
    	LL ans = n;
    	for(LL i = 2; i * i <= n; i++) {
    		if(n % i == 0) {
    			ans = ans / i * (i - 1);
    			while(n % i == 0) n /= i;
    		}
    	}
    	if(n != 1) ans = ans / n * (n - 1);
    	return ans;
    }
    
    LL work(LL n) {
    	LL ans = 0;
    	for(LL i = 1; i * i <= n; i++) {
    		if(n % i == 0) {
    			(ans += ksm(n, i) * getphi(n / i) % mod) %= mod;
    			if(i * i != n) (ans += ksm(n, n / i) * getphi(i) % mod) %= mod;
    		}
    	}
    	return ans * ksm(n, mod - 2) % mod;
    }
    
    int main() {
    	for(int T = in(); T --> 0;) printf("%lld
    ", work(in()));
    	return 0;
    }
    
  • 相关阅读:
    nodeName,nodeValue未知 xml 入库方案 The ElementTree iterparse Function
    如何:执行大型 XML 文档的流式转换 大XML文件解析入库的一个方法
    python curl_get-pip.py Installing with get-pip.py
    iptables List the rules in a chain or all chains
    goroutine 分析 协程的调度和执行顺序 并发写 run in the same address space 内存地址 闭包 存在两种并发 确定性 非确定性的 Go 的协程和通道理所当然的支持确定性的并发方式(
    数据库业界
    The MEAN stack is a modern replacement for the LAMP (Linux, Apache, MySQL, PHP/Python) stack
    Using Groovy To Import XML Into MongoDB
    虚拟机网络模式 桥接 网桥 交换机
    防止有内存泄漏并尽可能快地释放所有内存是内存管理的重要组成部分 长时间运行进程的内存泄漏
  • 原文地址:https://www.cnblogs.com/olinr/p/10359459.html
Copyright © 2011-2022 走看看