• 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;
    }
  • 相关阅读:
    listview删除item
    标准listview加图标布局
    android事件消费机制,从外传到里面,里面具有优先选择权,如果里面的不需要,则传递给外面一层消费
    listview 按最新数据展示
    给listview添加数据,添加数据之后即刻显示出来,并把数据放在listview列表的最前面
    EditText限制输入长度和限定输入数字
    josn解析常见的几种方法
    bnu Robots on a grid
    hdu 1348 Wall
    hdu poj Oulipo
  • 原文地址:https://www.cnblogs.com/Gloid/p/10164541.html
Copyright © 2020-2023  润新知