POJ - 2888 Magic Bracelet burnside引理 有限制的计数

因为珠子之间有限制,不能利用polya,我们只能回归到最原始的burnside引理看看能不能解决问题

burnside引理说的是什么那,,就是你只要给我每个置换对应的不动点个数,我就可以给你方案数

我们来尝试找出一个置换对应的不动点

因为只有旋转,所以,对于旋转k次这个置换,置换群被分为g=gcd(n,k)个循环,我们会发现,对于不动点,每个循环中柱子应该是一样的,所以我们只需要看连续的长为g的一段的方案数,即为不动点

不过这题很卡时间。。普通的快速矩阵幂很容易被卡,,因为矩阵快速幂的话,如果二进制位有k位,一般的矩阵快速幂要计算,k+(次幂的二进制位1的个数),,然后先算出2的次幂的乘积,,,,然后就变成,计算,,(次幂的二进制1的个数)次,,

就从T到600ms,,


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<,int> PIII;
typedef pair PII;
const double eps=1e-5;
const int MX=1e5+5;
const int P=9973;
int n,m,k;
int prime[MX];
bool isprime[MX];
struct Matrix
{
    int n,m[111][111];
    void init(int nn,int t)
    {
        n=nn;
        for(int i=0; iP)ans.m[i][j]%=P;
                        }
                    }
                ans.m[i][j]%=P;
            }
        return ans;
    }
} M,er[32];
void init()
{
    prime[0]=0;
    mem(isprime,1);
    for(int i=2; i>=1;
    }
    return ans;
}
Matrix Matrix_pow(Matrix a,int x)
{
    Matrix ans;
    ans.init(a.n,1);
    int cnt=0;
    while(x)
    {
        if(x&1)ans=ans*er[cnt];
        cnt++;
        x>>=1;
    }
    return ans;
}
int ans;
int pi[MX][2],pc;
void dfs(int dep,int val,int phi)
{
    if(dep==pc+1)
    {
        // cout<>T;
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        M.init(m,0);
        for(int i=1; i<=k; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            u--,v--;
            M.m[u][v]=M.m[v][u]=1;
        }
        for(int i=0; i


你可能感兴趣的:(POJ - 2888 Magic Bracelet burnside引理 有限制的计数)