本小结会不断更新,转载请注明出处:http://blog.youkuaiyun.com/xdu_truth/article/details/8033524
(1)循环:
在一个置换下 如果x1->x2,x2->x3,...,xn->x1;
x1,x2,x3,...,xn就形成了一个循环。
(2)ploya定理:
定义ck为在置换ak下的循环总数
设G = {a1,a2,a3,...,a|G|}是N ={1,2,3,...,N}上的置换群,现用m种颜色对着N个点染色,则不同的染色方案数为:
S = (m^c1 + m^c2 + ... + m^c|G|)/|G|
(3)常见置换的循环数:
旋转: n个点顺时针(或逆时针)旋转i个位置的置换,循环数为gcd(n,i)
翻转:
n为偶数时: 对称轴不过顶点:循环数为n/2;
对称轴过顶点:循环数为n/2+1;
n为奇数时:循环数为(n+1)/2;
pku2409 Let it Bead (公式题)
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int gcd(int a,int b)
{
return b==0 ? a:gcd(b,a%b);
}
int _pow(int p,int n)
{
int ret = 1;
while(n)
{
if(n&1)ret *= p;
p *= p;
n /= 2;
}
return ret;
}
int main()
{
int n,m;
while(~scanf("%d%d",&m,&n),n|m)
{
int ans = 0;
for(int i=1;i<=n;i++)
ans += _pow(m,gcd(n,i));
if(n&1)
ans += n*_pow(m,(n+1)/2);
else ans += (n/2)*_pow(m,n/2)+(n/2)*_pow(m,n/2+1);
ans /= (2*n);
printf("%d\n",ans);
}
return 0;
}
另外POJ上还有个公式题http://poj.org/problem?id=1286
这个题注意项链珠数为0的情形,之前一直RE,把我恶心到了。
----------------------------------------------------我是华丽的分割线---------------------------------------------------
pku2154 Color
题意:给出两个整数n和p,代表n个珠子,n种颜色,要求不同的项链数(旋转重合算同一种,翻转重合不算同一种),并对结果mod(p)处理。
不错的一个数学题,
根据ploya定理,结果为:(1/n * ∑n^gcd(n,i)) % p (i=1,..,n)
但是n<=1000000000,显然这个公式需要化简一下。
gcd(n,i)的所有取值是n的所有约数,所以对于某个约数x,我们考虑n^x系数:
由于gcd(n,i) = x ,
那么gcd(n/x,i/x) = 1,
所以系数即为所有满足上式的i的个数,即欧拉函数 euler(n/x);
这样公式就化简为了: (1/n * ∑Euler(n/x)(n^x)) % p (x为n的所有约数)
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int n,mod;
int powmod(int p,int m)
{
int ret = 1;
while(m)
{
if(m&1)ret=(ret * p)%mod;
p = (p*p)%mod;
m >>= 1;
}
return ret;
}
int euler(int x)
{
int res = x;
for(int i=2;i<(int)sqrt(x*1.0)+1;i++)
{
if(x%i == 0)
{
res = res/i*(i-1);
while(x%i==0)
x/=i;
}
}
if(x>1)res = res/x*(x-1);
return res%mod;
}
int main()
{
//freopen("input.txt","r",stdin);
int cases;
scanf("%d",&cases);
while(cases-- && scanf("%d%d",&n,&mod))
{
int ans = 0;
for(int x=1;x*x<=n;x++)
{
if(n%x==0)
{
ans = (ans+euler(n/x)*powmod(n%mod,x-1))%mod;
if(n/x != x)ans = (ans+euler(x)*powmod(n%mod,n/x-1))%mod;
}
}
printf("%d\n",ans);
}
return 0;
}
本文介绍了ploya定理及其在计算不同项链数问题中的应用。通过置换群的概念,讨论了旋转和翻转的循环数,并给出了公式 `(1/n * Σ Euler(n/x)(n^x)) % p`,其中`Euler(n/x)`是欧拉函数,用于处理n个珠子,n种颜色,考虑旋转但不考虑翻转的项链数模p的计算。
17万+

被折叠的 条评论
为什么被折叠?



