zoukankan      html  css  js  c++  java
  • BZOJ1004 HNOI2008Cards(Burnside引理+动态规划)

      直接给了一个置换群(当然要自己手动加上不洗牌的情况)。考虑求不动点数量即可。对于一个置换,求出所有循环的长度,然后设f[i][x][y]为给前i个循环着色后,用了x张红色卡片、y张绿色卡片的方案数,dp一发即可。

      upd:为啥我写的应该不是假算法却好像也被hack掉了?不管了已经忘了这是啥题肯定哪写挂了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 66
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,A,B,C,m,P,a[N],cycle[N],f[N][N][N],ans;
    bool flag[N];
    int calc()
    {
        memset(f,0,sizeof(f));f[0][0][0]=1;int s=0;
        for (int j=1;j<=n;j++)
        {
            s+=cycle[j];
            for (int x=0;x<=A;x++)
                for (int y=0;y<=B;y++)
                {
                    int z=s-x-y;if (z>C) continue;
                    if (x>=cycle[j]) f[j][x][y]+=f[j-1][x-cycle[j]][y];
                    if (y>=cycle[j]) f[j][x][y]+=f[j-1][x][y-cycle[j]];
                    if (z>=cycle[j]) f[j][x][y]+=f[j-1][x][y];
                    f[j][x][y]%=P;
                }
        }
        return f[n][A][B];
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj1004.in","r",stdin);
        freopen("bzoj1004.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        A=read(),B=read(),C=read(),m=read(),P=read();
        for (int i=1;i<=m;i++)
        {
            for (int j=1;j<=n;j++)
            a[read()]=j;
            memset(flag,0,sizeof(flag));n=0;
            for (int j=1;j<=n;j++)
            if (!flag[j])
            {
                int x=a[j];flag[j]=1;cycle[++n]=1;
                while (x!=j) flag[x]=1,cycle[n]++,x=a[x];
            }
            ans+=calc();
        }
        n=A+B+C,m++;for (int i=1;i<=n;i++) cycle[i]=1;ans+=calc();
        for (int i=1;i<P;i++) if (i*m%P==1) {ans=ans*i%P;break;}
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    C#
    C#
    css
    css
    css
    css
    css
    Css
    Javascript
    ASP.NET MVC
  • 原文地址:https://www.cnblogs.com/Gloid/p/10164541.html
Copyright © 2011-2022 走看看