UVA10294——Polya定理

题目链接:https://vjudge.net/contest/332708#problem/Q

题目大意:

n 个珠子组成的 项链,t 种颜色去染, 问有多少本质不同的项链;

经旋转,翻转一样的视为同一种项链。

题解:等价类计数问题,用Polya定理和burnside定理解决。

代码有详解。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#define rp(i, s, t) for (i = s; i <= t; i++)
#define RP(i, s, t) for (i = t; i >= s; i--)
#define ll long long
#define ull unsigned long long
using namespace std;
inline int read()
{
    int x = 0, t = 1;
    char ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-')
        ch = getchar();
    if (ch == '-')
        t = -1, ch = getchar();
    while (ch <= '9' && ch >= '0')
        x = x * 10 + ch - 48, ch = getchar();
    return x * t;
}
inline void write(int x)
{
    char F[200];
    int tmp = x > 0 ? x : -x;
    if (x < 0)
        putchar('-');
    int cnt = 0;
    while (tmp > 0)
    {
        F[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0)
        putchar(F[--cnt]);
}
ll gcd(ll a, ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}
/*总共有两种情况:旋转和翻转
旋转:逆时针旋转i颗珠子的间距,则珠子0,i,2i,....构成一个循环,循环内有n/gcd(i,n)个元素
一共有gcd(i,n)个循环,那么根据Polya定理:不动点个数 a=∑(t^(gcd(i,n))) {0<=i<=n-1}
翻转:分为两种情况讨论,n为奇数和n为偶数
当n为奇数时,对称轴为n条,每条对称轴形成(n-1)/2个长度为2的循环和1个长度为1的循环,即(n+1)/2个循环((n-1)/2+1).
所以这些置换的不动点个数为 b = n*t^( (n+1)/2 ).
当n为偶数时,有两种对称轴:穿过珠子和不穿过珠子
穿过珠子时,对称轴为n/2条,形成n/2-1个长度为2的循环和两个长度为1的循环。
不穿过珠子时,对称轴为n/2条,形成n/2个长度为2的循环
故n为偶数时置换的不动点的个数为 b = n*(t^(n/2+1)+t(n/2))/2;
*/
int main()
{
    int n, t;
    while (n = read(), t = read())
    {
        if (!n)
            break;
        ull pow[100]; //数组用unsigned long long 来存储,不然会炸
        pow[0] = 1;
        int i;
        rp(i, 1, n) pow[i] = pow[i - 1] * t; //预处理求出t的幂次方
        ull a = 0;
        rp(i, 0, n - 1) a += pow[gcd(i, n)]; //旋转的情况
        ull b = 0;
        //翻转的情况
        if (n & 1)
            b = n * pow[(n + 1) / 2]; //n为奇数
        else
            b = n / 2 * (pow[n / 2 + 1] + pow[n / 2]); //n为偶数
        printf("%llu %llu\n", a / n, (a + b) / 2 / n);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值