• 【洛谷 P4980】 【模板】Pólya 定理


    简单的写一下吧,Polya定理就是用来求等价类的数目的。
    什么是等价类?经过某些置换操作能相等的两个的状态属于同一个等价类。
    然后是一些基本的定理,
    等价类的数目(C)为置换群的不动点的平均值,
    (C=frac{1}{|G|}sum _{fin G}k^{m(f)})
    其中,(G)为置换群,(f)为其中的一种置换,(m(f))表示把置换(f)看成(m(f))(f)的乘积(可以理解为循环节),(k)表示颜色的种类数。
    显然本题的置换群就是({旋转0个,旋转1个,...,旋转n个})
    考虑旋转(k)个的循环节(p),显然(p|k),同时(p|n),所以旋转(k)个的贡献就是(n^{gcd(k,n)})
    那么最终答案就是(frac{1}{n}sum_{i=0}^{n-1}n^{gcd(i,n)})
    直接求显然是(O(nlogn))
    (n)的约数为(m)个,考虑到不同(gcd)的数量只有(m)个,于是枚举约数(d)
    (k=e*d),显然满足(gcd(k,n)=d)(e)要与(frac{n}{d})互质,那么这样的(k)(varphi{frac{n}{d}})
    于是最终答案就是(frac{1}{n}sum_{d|n}n^dvarphi{frac{n}{d}})

    #include <bits/stdc++.h>
    using namespace std;
    const int MOD = 1e9 + 7;
    int T, n;
    int gcd(int a, int b){
    	return !b ? a : gcd(b, a % b);
    }
    long long ans;
    long long fast_pow(long long a, int k){
    	long long ans = 1;
    	while(k){
    		if(k & 1) ans = ans * a % MOD;
    		a = a * a % MOD; k >>= 1;
    	}
    	return ans;
    }
    int phi(int x){
    	if(x == 1) return 1;
    	int y = x;
    	int p = sqrt(x);
    	for(int i = 2; i <= p && x != 1; ++i)
    		if(x % i == 0){
    			y = y / i * (i - 1);
    			while(x % i == 0) x /= i;
    		}
    	if(x != 1) y = y / x * (x - 1);
    	return y;
    }
    int main(){
    	scanf("%d", &T);
    	while(T--){
    		scanf("%d", &n); ans = 0;
    		int p = sqrt(n);
    		for(int i = 1; i <= p; ++i)
    			if(n % i == 0){
    				ans = (ans + fast_pow(n, i) * phi(n / i)) % MOD;
    				if(i * i != n) ans = (ans + fast_pow(n, n / i) * phi(i)) % MOD;
    			}
    		printf("%lld
    ", ans * fast_pow(n, MOD - 2) % MOD);
    	}
    	return 0;
    }
    
  • 相关阅读:
    kioptrix-1
    4.4 CSRF
    upload-labs 练习笔记
    4.3 XSS
    外国人是怎样读编程书的呢?
    如何快速学习新语言
    Go开发环境配置
    Golang Package I
    MVC模式小结
    Flask基础知识
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/15286908.html
Copyright © 2020-2023  润新知