zoukankan      html  css  js  c++  java
  • 【NOIP/CSP2019】D2T1 Emiya 家今天的饭

    这个D2T1有点难度啊

    原题:

     

    花了我一下午的时间,作为D2T1的确反常

    条件很奇怪,感觉不太直观,于是看数据范围先写了个暴力

    写暴力的时候我就注意到了之前没有仔细想过的点,烹饪方式必须不同

    虽然a很大,但是n只有100,即总菜数比较小

    而且虽然m和a都很大,但是一种方法只能做一道菜,即选一种食材

    所以搜索枚举每种方法选哪种食材,最后检查方案是否满足条件

    这样可以拿到32分

    需要注意到一点很关键的性质

    不管什么方案,最多只有一个食材能超过n/2,看到n/2要敏感

    那么如果无视n/2的限制,直接dp就vans了,接下来只需要去掉不合法的方案

    枚举哪一种食材超过n/2,可以发现此时食材只有两种,枚举到的食材和其他的食材

    需要表达的状态数大大减少

    设计状态,f[i][j][k]表示直到第i种方式,总共选了j道菜,其中k道菜用当前枚举食材

    这样可以拿到82分

    然后就不会了233

    这个递推又没有决策,咋优化啊

    本着单个题目思考时间不能过长的原则,观摩了python96的题解:

    https://blog.csdn.net/weixin_37517391/article/details/103110646

    立刻点化233

    确实不太好想,果然适时看题解效率更高

    我们记录状态的时候不必记录两类食材的数量,只需记录二者差值即可

    只要差值相同,不同的数量对于合法性的判断都是等价的

    那么以前的3维dp就优化到2维,可以ac了

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 #define LL long long
     8 const int mo=998244353;
     9 int rd(){int z=0,mk=1;  char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
    11     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    12     return z*mk;
    13 }
    14 int n,m,a[110][2100];
    15 LL ans=0;
    16 int cnt[2100];
    17 LL s[110];
    18 LL f7[110][110][110];
    19 LL f[110][210];
    20 bool chck(int x){
    21     if(!x)  return false;
    22     //注意x=0时必须特判,因为此时cnt也全是0,下面条件不会成立
    23     for(int i=1;i<=m;++i)if(cnt[i]>x/2)  return false;
    24     return true;
    25 }
    26 void dfs(int x,int y,LL z){
    27     if(x==n+1){
    28         if(chck(y))  ans=(ans+z)%mo;
    29         return ;
    30     }
    31     dfs(x+1,y,z);
    32     for(int i=1;i<=m;++i)if(a[x][i]){
    33         ++cnt[i];
    34         dfs(x+1,y+1,z*a[x][i]%mo);
    35         --cnt[i];
    36     }
    37 }
    38 LL gan(int x){
    39     memset(f7,0,sizeof(f7));
    40     f7[0][0][0]=1;
    41     for(int i=1;i<=n;++i)for(int j=0;j<=i;++j)for(int k=0;k<=j;++k){
    42         f7[i][j][k]=f7[i-1][j][k];
    43         if(j && k)  f7[i][j][k]=(f7[i][j][k]+f7[i-1][j-1][k-1]*a[i][x]%mo)%mo;
    44         if(j)  f7[i][j][k]=(f7[i][j][k]+f7[i-1][j-1][k]*(s[i]-a[i][x])%mo)%mo;
    45     }
    46     LL bwl=0;
    47     for(int i=1;i<=n;++i)for(int j=i/2+1;j<=i;++j)  bwl=(bwl+f7[n][i][j])%mo;
    48     return bwl;
    49 }
    50 LL ganisok(int x){
    51     memset(f,0,sizeof(f));
    52     f[0][n]=1;
    53     for(int i=1;i<=n;++i)for(int j=0;j<=n+n;++j){
    54         f[i][j]=f[i-1][j];
    55         if(j)  f[i][j]=(f[i][j]+f[i-1][j-1]*a[i][x]%mo)%mo;
    56         if(j<n+n)  f[i][j]=(f[i][j]+f[i-1][j+1]*(s[i]-a[i][x]%mo))%mo;
    57     }
    58     LL bwl=0;
    59     for(int i=n+1;i<=n+n;++i)  bwl=(bwl+f[n][i])%mo;
    60     return bwl;
    61 }
    62 int main(){
    63     //freopen("ddd.in","r",stdin);
    64     cin>>n>>m;
    65     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)  a[i][j]=rd();
    66     if(n<=10 && m<=3){
    67         dfs(1,0,1);
    68         cout<<ans<<endl;
    69     }
    70     else if(n<=40 && m<=500){
    71         for(int i=1;i<=n;++i){
    72             s[i]=0;
    73             for(int j=1;j<=m;++j)  s[i]=(s[i]+a[i][j])%mo;
    74         }
    75         LL bwl=1;
    76         for(int i=1;i<=n;++i)  bwl=bwl*(s[i]+1)%mo;
    77         bwl-=1;
    78         for(int i=1;i<=m;++i)  bwl=(bwl-gan(i))%mo;
    79         cout<<(bwl%mo+mo)%mo<<endl;
    80     }
    81     else{
    82         for(int i=1;i<=n;++i){
    83             s[i]=0;
    84             for(int j=1;j<=m;++j)  s[i]=(s[i]+a[i][j])%mo;
    85         }
    86         LL bwl=1;
    87         for(int i=1;i<=n;++i)  bwl=bwl*(s[i]+1)%mo;
    88         bwl-=1;
    89         for(int i=1;i<=m;++i)  bwl=(bwl-ganisok(i))%mo;
    90         cout<<(bwl%mo+mo)%mo<<endl;
    91     }
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    HTML iframe, 获取iframe子页面中的元素(基于JavaScript)
    微信小程序中引入VR全景图
    git创建分支,提交代码详细流程(保姆级)
    Vue项目中使用Axios封装http请求
    node搭建本地服务器后端解决跨域问题
    ant design Upload组件上传文件类型
    使用nodejs连接mysql数据库实现增删改查 连接Node.js时报错“Cannot GET /”
    后端返回文件流,前端处理进行文件下载
    JS判断是否是数组的四种做法
    Js常用方法:JS字符串截取、数组截取等
  • 原文地址:https://www.cnblogs.com/cdcq/p/11900314.html
Copyright © 2011-2022 走看看