U - Necklace LightOJ - 1419 (初识 poyla 定理)

链接:Orz

题意:n 个珠子,有 k 种颜色,问:有多少种方法本质不一样的方法填色 (旋转几个相同就是一样的)

题解:poyla定理吧,百度百科上有图:

          

          关于图里面的一些解释 

         (置换群,你就看成有 n 个成员的一个环啥的 !?)

          1.置换,首先要知道置换是个什么东西

                        上面这个    1   2    3   4   5 

                        到下面这 a1  a2  a3  a4  a5 的映射算一种置换

                       ( 像正方形旋转那种,也可以看成顶点的置换 )

          2. 循环节数,在一个置换中,有几个循环,像是  1 2 3 4  , { 1,3 },{ 2, 4}可以互到达的有 2 个,所以循环节数为 2

                                                                                     3 4 1 2

          3. p1,p2,.....,pk ,就是每一步走的步数 ( 一下走 1 步,一下走 2 步什么?)

           

           那么上面那个式子变成了 L = 1 / 步数种数 * (∑ m ^ (每种步数构成的循环节数))

           怎么求这个循环节数呢 {

                     每次走 i 步, 走回原来的位置 , 需要的次数 cnt 是:每次走 i 步的这样的走 lcm(i, n) / i步数

                     那么在这 cnt 次的走动中,每个踩到的值可以拿出来成一个循环

                    比如  1 2 3 4   { 1, 3 } { 2 , 4 }就是可以拿出来,那么这个置换存在 2 个循环节数

                              3 4 1 2 
                    一共可以走 1 步到走 n 步,他们的循环节数就是 n / cnt ,(cnt 一个循环,n / cnt 个循环节数)

            }

            那么 ans = 1/n * ∑ (m ^ (n/cnt))

             cnt = lcm(i,n) / i  , n / lcm( i , n) / i  === n * i / lcm (i,n) === gcd(i,n)

            那么 ans = 1/n * ∑ (m ^ (gcd(i,n)))

            所以有代码:

#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
#define rep(i,a,b) for(int i=a;i<=b;i++)
typedef long long ll;

long long gcd(ll a,ll b) {
	return b ? gcd(b,a%b) : a;
}
long long bigmod(ll a,ll b) {
	ll res = 1;
	while(b) {
		if(b&1) res = res * a % mod;
		b >>= 1;
		a = a * a % mod;
	}
	return res;
}
int main() {
	int T;
	scanf("%d",&T);
	rep(t,1,T) {
		int n,k;
		long long sum = 0;
		scanf("%d %d",&n,&k);
		rep(i,1,n) {
			sum = (sum + bigmod(k,gcd(i,n))) % mod;
		}
		sum = sum * bigmod(n,mod-2) % mod;
		printf("Case %d: %lld\n",t,sum);
	}
}
/*
   ∑quick(k,gcd(i,n))
  ---------------------
          n
*/

        

 

最后呢 , poyla 有很多题不只是这一种形式 , 比如翻转什么的 !? HDU --- 3923 Invoker  这个题就包含了翻转,可以试着写一写

          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值