[POJ 2409] Let it Bead

本文探讨了在给定长度的环上进行染色时,如何计算在翻转和旋转后本质不同的方案数量。通过使用Polya定理,文章详细解释了如何处理旋转和翻转操作,最终给出了一种高效的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、题目

题目描述

有长度为 n n n的环 m m m染色,问翻转和旋转之后本质不同的方案数。

数据范围

n m ≤ 32 nm\leq32 nm32

二、解法

polya \text{polya} polya版题,一共 2 n 2n 2n个置换。

首先考虑旋转,旋转 i i i次后的分解个数为 gcd ⁡ ( i , n ) \gcd(i,n) gcd(i,n),贡献为 ∑ i = 1 n m gcd ⁡ ( i , n ) \sum_{i=1}^nm^{\gcd(i,n)} i=1nmgcd(i,n)

然后考虑翻转,分奇偶性讨论,如果为偶数,那么过两点有 n 2 \frac{n}{2} 2n的贡献是 m n / 2 + 1 m^{n/2+1} mn/2+1,那么过空隙有 n 2 \frac{n}{2} 2n的贡献是 m n / 2 m^{n/2} mn/2;如果为奇数,那么只能过一点和一个空隙,一共有 n n n个,贡献为 m n / 2 + 1 m^{n/2+1} mn/2+1

#include <cstdio>
#define int long long
int read()
{
    int x=0,flag=1;
    char c;
    while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*flag;
}
int n,m,ans;
int gcd(int a,int b)
{
    return !b?a:gcd(b,a%b);
}
int qkpow(int a,int b)
{
    int r=1;
    while(b>0)
    {
        if(b&1) r=r*a;
        a=a*a;
        b>>=1;
    }
    return r;
}
signed main()
{
    while(~scanf("%lld %lld",&m,&n) && n+m)
    {
        ans=0;
        if(!n)
        {
            puts("0");
            continue ;
        }
        for(int i=1;i<=n;i++)
            ans+=qkpow(m,gcd(i,n));
        if(n&1) ans+=n*qkpow(m,n/2+1);
        else ans+=(n/2)*qkpow(m,n/2)+(n/2)*qkpow(m,n/2+1);
        ans/=2*n;
        printf("%lld\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值