zoukankan      html  css  js  c++  java
  • 训练日志 2 (7.7)

    T1 「SDOI2015」排序

      Loj上的一道暴搜题,挺水的(但是考试的时候还是只拿了10分,还是水的)

      考试的时候没有好好的想一想,其实再想想,在努努力打个大暴搜,没准儿能A。

      简单推导可以发现,只要这个数列可以通过某种方式回到合法状态,那么无论操作的顺序如何,结果都是一样的。那么就显然了,假设操作了n次,那答案就是n的阶乘。(考试的时候也仅仅想到了这儿,加了个特判。)

      对于每一组数列,我们可以找到不止一种(指的是一个操作系列)操作来还原它,比如

            1 10 11 12 13 14 15 16 9 2 3 4 5 6 7 8

      在该数组中,可以先将1与9换,也可以将10与2换,同样可以还原回去。

      发现了这一点,就可以开始暴搜了。

      设cz(操作)初始为1,一共进行了num次操作,逐层往下递归,每次cz*2,直到操作达到最大即2n,这时搜一遍串判断该串是否合法,不合法返回,反之求num的阶乘。

      注意各个情况要考虑到,换对象能各种换,2×2=4。

      结束了。

      小弟不才。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define Mojie using namespace std
     5 Mojie;
     6 int n,m;
     7 int a[1<<13];
     8 bool flag[1<<13];
     9 int ans;
    10 void Dfs(int ,int );
    11 void Swap(int ,int ,int );
    12 int main()
    13 {
    14     scanf("%d",&n);
    15     m=(1<<n);
    16     for (int i=1; i<=m; ++i)
    17         {scanf("%d",&a[i]);}
    18     Dfs(1,0);
    19     printf("%d
    ",ans);
    20 }
    21 void Dfs(int cz,int num)
    22 {
    23     if (cz==m)
    24     {
    25         for (int i=1; i<=m; ++i)
    26             if (a[i]!=i)
    27                 return ;
    28         int res=1;
    29         for (int i=2; i<=num; ++i)
    30             res*=i;
    31         ans+=res;
    32         return ;
    33     }
    34     int lh=cz<<1,tt=0;
    35     memset(flag,0,sizeof(flag));
    36     for (int i=1; i<=m; i+=lh)
    37     {
    38         if (a[i]+cz==a[i+cz]) flag[i]=1;
    39         else ++tt;
    40     }
    41     if (tt>2) return;
    42     else if (tt==0) Dfs(cz<<1,num);
    43     else if (tt==1)
    44     {
    45         int y,t=0;
    46                 for (int i=1; i<=m; i+=lh)
    47                     if (!flag[i])
    48                             {y=i; break;}
    49         Swap(y,y+cz,cz);
    50         Dfs(cz<<1,num+1);
    51         Swap(y,y+cz,cz);
    52     }
    53     else 
    54     {
    55         int x[2],t=0;
    56                 for (int i=1; i<=m; i+=lh)
    57                         if (!flag[i])
    58                                 x[t++]=i;
    59         Swap(x[0],x[1],cz);
    60         Dfs(cz<<1,num+1);
    61         Swap(x[0],x[1],cz);
    62         Swap(x[0]+cz,x[1]+cz,cz);
    63         Dfs(cz<<1,num+1);
    64         Swap(x[0]+cz,x[1]+cz,cz);
    65         Swap(x[0],x[1]+cz,cz);
    66         Dfs(cz<<1,num+1);
    67         Swap(x[0],x[1]+cz,cz);
    68         Swap(x[0]+cz,x[1],cz);
    69         Dfs(cz<<1,num+1);
    70         Swap(x[0]+cz,x[1],cz);
    71     }
    72 }
    73 void Swap(int l,int r,int step)
    74 {
    75     for (int i=l,j=r; i<l+step,j<r+step; ++i,++j)
    76         swap(a[i],a[j]);
    77 }
    排序

      

    T3  【CQOI2011】放棋子

      暴搜是不会实现的了,考虑dp。

      定义dp[i][j][k]为在任意i行任意j列放置前k中棋子的方案数,g[i][j][k]为在任意i行任意j列放k个同种棋子的方案数

      dp[i][j][k]=Σdp[l][r][k-1]*g[i-l][j-r][a[k]]*C(n-l,i-l)*C(m-r,j-r) (l和r取不到i和j)

      g[i][j][k]=C(k,i*j)-Σg[l][r][k]*C(l,i)*C(r,j) (注意理解一下这里,l,r>=0且l<=i||r<=j)

      求g的加和不好求,用到了容斥。

      注意dp定义,任意i行j列。

      还有一点就是取模的问题,对于1e9+9的模数,如果不及时取模就会爆long long,在算g时还会算成负数。

      小弟不才。

      

     1 #include<cstdio>
     2 #include<iostream>
     3 #define Ojbk using namespace std
     4 Ojbk;
     5 const long long mod=1e9+9;
     6 int n,m,c,maxx;
     7 long long F[10003],Finv[10003],inv[10003];
     8 int a[11];
     9 long long f[33][33][33],g[33][33][333];
    10 void Init();
    11 inline long long Comb(int ,int );
    12 int main()
    13 {
    14     scanf("%d%d%d",&n,&m,&c);
    15     Init();
    16     for (int i=1; i<=c; ++i)
    17         {scanf("%d",&a[i]); maxx=max(a[i],maxx);}
    18     for (int k=1; k<=c; ++k)
    19         for (int i=1; i<=n; ++i)
    20             for (int j=1; j<=m; ++j)
    21             {
    22                 g[i][j][a[k]]=Comb(i*j,a[k]);
    23                 for (int l=1; l<=i; ++l)
    24                     for (int r=1; r<=j; ++r)
    25                     {
    26                         if (i==l and j==r) break;
    27                         g[i][j][a[k]]-=g[l][r][a[k]]*1ll%mod*Comb(i,l)%mod*Comb(j,r)%mod;
    28                         g[i][j][a[k]]=(g[i][j][a[k]]%mod+mod)%mod;
    29                     }
    30             }
    31     f[0][0][0]=1;
    32     for (int k=1; k<=c; ++k)
    33         for (int i=1; i<=n; ++i)
    34             for (int j=1; j<=m; ++j)
    35                 for (int l=0; l<i; ++l)
    36                     for (int r=0; r<j; ++r)
    37                     {
    38                         f[i][j][k]+=f[l][r][k-1]%mod*g[i-l][j-r][a[k]]%mod*1ll*Comb(n-l,i-l)%mod*Comb(m-r,j-r)%mod;
    39                         f[i][j][k]=(f[i][j][k]%mod+mod)%mod;
    40                     }
    41     long long ans=0;
    42     for (int i=1; i<=n; ++i)
    43         for (int j=1; j<=m; ++j)
    44             {ans+=f[i][j][c]; ans=(ans%mod+mod)%mod;}
    45     printf("%lld
    ",ans);
    46     return 0;
    47 }
    48 inline long long Comb(int x,int y)
    49 {
    50     if (y>x) return 0;
    51     return F[x]%mod*1ll*Finv[y]%mod*Finv[x-y]%mod;
    52 }
    53 void Init()
    54 {
    55     inv[1]=1;
    56     for (int i=2; i<=10000; ++i)
    57         inv[i]=(mod-mod/i)*1ll*inv[mod%i]%mod;
    58     F[0]=Finv[0]=1;
    59     for (int i=1; i<=10000; ++i)
    60     {
    61         F[i]=F[i-1]*1ll*i%mod;
    62         Finv[i]=Finv[i-1]%mod*1ll*inv[i]%mod;
    63     }
    64 }
    放棋子

      

      永不放弃

  • 相关阅读:
    VS2013 此模板尝试加载组件程序集”NuGet.VisualStudio.interop,Version=1.0.0.0 的解决办法
    备份集中的数据库备份与现有的xx数据库不同”解决方法
    Couchbase 集群小实践
    EF5+MVC4系列(1) Podwerdesigner15.1设计数据库;PD中间表和EF实体模型设计器生成中间表的区别;EF5.0 表关系插入数据(一对多,多对多)
    Vue个人笔记
    [转载] HashMap的工作原理-hashcode和equals的区别
    用VS Code写C#
    MongoDB学习笔记一:MongoDB基础
    Vue学习笔记十三:Vue+Bootstrap+vue-resource从接口获取数据库数据
    Vue学习笔记十二:vue-resource的基本使用
  • 原文地址:https://www.cnblogs.com/LH-Xuanluo/p/11165867.html
Copyright © 2011-2022 走看看