zoukankan      html  css  js  c++  java
  • bzoj 1004 Cards & poj 2409 Let it Bead —— 置换群

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1004

    关于置换群:https://www.cnblogs.com/nietzsche-oier/p/6883880.html

    https://files-cdn.cnblogs.com/files/HocRiser/Burnside.pdf

    原来 burnside 引理中的“不动点”是指一种不变化的方案啊;

    这道题就用 burnside 引理,但给出的 m 个置换还不是置换群,需要再加一个单位元,即 ( a[i] = i ) 的置换;

    用三维DP求出每种置换的“不动点”个数,枚举可以通过记录总数而减少一维。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const xn=65,xm=25;
    int n,m,sr,sb,sg,a[xn],f[xm][xm][xm],mod,tot;
    bool vis[xn];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    ll pw(ll a,int b)
    {
      ll ret=1;
      for(;b;b>>=1,a=(a*a)%mod)if(b&1)ret=(ret*a)%mod;
      return ret;
    }
    int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;}
    void dfs(int x)
    {
      tot++; vis[x]=1;
      if(!vis[a[x]])dfs(a[x]);
    }
    int main()
    {
      sr=rd(); sb=rd(); sg=rd(); m=rd(); mod=rd(); 
      n=sr+sb+sg; m++;
      for(int i=1;i<=m;i++)
        {
          memset(vis,0,sizeof vis);
          memset(f,0,sizeof f); f[0][0][0]=1;//
          if(i==m)for(int j=1;j<=n;j++)a[j]=j;
          else for(int j=1;j<=n;j++)a[j]=rd(),vis[j]=0;
          tot=0; int res=0;
          for(int j=1;j<=n;j++)
        {
          if(vis[j])continue;
          tot=0; dfs(j); res+=tot;
          for(int j=sr;j>=0;j--)
            for(int k=sb;k>=0;k--)
              //for(int l=sg;l>=0;l--)
              {
            int l=res-j-k; if(l<0)continue;
            if(j>=tot)f[j][k][l]=upt(f[j][k][l]+f[j-tot][k][l]);
            if(k>=tot)f[j][k][l]=upt(f[j][k][l]+f[j][k-tot][l]);
            if(l>=tot)f[j][k][l]=upt(f[j][k][l]+f[j][k][l-tot]);
              }
        }
        }
      printf("%lld
    ",(ll)f[sr][sb][sg]*pw(m,mod-2)%mod);
      return 0;
    }

    题目:http://poj.org/problem?id=2409

    Polya 定理裸题;

    gcd 可以从模的剩余系的角度来看;

    注意加上翻转后有 2n 个置换。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const xn=40;
    int n,m;
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    int pw(int a,int b)
    {
      int ret=1;
      for(;b;b>>=1,a=a*a)if(b&1)ret=ret*a;
      return ret;
    }
    int main()
    {
      while(1)
        {
          scanf("%d%d",&m,&n);
          if(!m&&!n)return 0;
          int ans=0; 
          for(int i=1;i<=n;i++)ans+=pw(m,gcd(n,i));
          if(n%2)ans+=n*pw(m,n/2+1);
          else ans+=n/2*pw(m,n/2)+n/2*pw(m,n/2+1);
          printf("%d
    ",ans/2/n);//2n
        }
      return 0;
    }
  • 相关阅读:
    MVC路由测试
    关于Dapper的使用笔记3
    关于Dapper的使用笔记2
    关于Dapper的使用笔记1
    关于WCF与Autofac的整合
    js获取页面元素距离浏览器工作区顶端的距离
    document.body.scrollTop和document.documentElement.scrollTop 以及值为0的问题
    js实现获取对象key名
    微信小程序分包跳转主包页面
    js禁止页面滚动
  • 原文地址:https://www.cnblogs.com/Zinn/p/10061221.html
Copyright © 2011-2022 走看看