zoukankan      html  css  js  c++  java
  • luogu11月月赛T3咕咕咕(组合数学)

    题目描述

    小 F 是一个能鸽善鹉的同学,他经常把事情拖到最后一天才去做,导致他的某些日子总是非常匆忙。

    比如,时间回溯到了 2018 年 11 月 3 日。小 F 望着自己的任务清单:

    1. 看 iG 夺冠;
    2. 补月赛题的锅。

    小 F 虽然经常咕咕咕,但他完成任务也是很厉害的,他一次性可以完成剩余任务的任一非空子集。比如,他现在可以选择以下几种中的一种:

    1. 看 iG 夺冠;
    2. 补月赛题的锅;
    3. 一边看 iG 夺冠的直播,一边补锅。

    当然,比赛实在是太精彩了,所以小 F 就去看比赛了。

    不过,当金雨从天而降、IG 举起奖杯之时,小 F 突然心生愧疚——锅还没补呢!于是,小 F 的内心产生了一点歉意。

    这时小 F 注意到,自己总是在某些情况下会产生歉意。每当他要检查自己的任务表来决定下一项任务的时候,如果当前他干了某些事情,但是没干另一些事情,那么他就会产生一定量的歉意——比如,无论他今天看没看比赛,只要没有补完月赛的锅,他都会在选择任务的时候产生 11 点歉意。小 F 完成所有任务后,他这一天的歉意值等于他每次选择任务时的歉意之和。

    过高的歉意值让小 F 感到不安。现在,小 F 告诉你他还有 n 项任务,并告诉你在 m 种情况中的一种的情况下,小 F 会产生 ai 点歉意。请你帮忙计算一下,小 F 在那一天所有可能的完成所有任务方式的歉意值之和是多少。

    由于答案可能很大,你只需要输出答案对 998244353 取模即可。

    输入输出格式

    输入格式:

    输入一行两个整数 n, m,表示有 n 项任务,在 m 种情况中下小 F 会产生歉意值。

    输入接下来 m 行,每行有一个长度为 n 的 0-1 串  和一个歉意值 ai,ai 为 0/1 表示第 j 项任务此时没做 / 已经做了。

    详情请参考样例和样例解释。

    输出格式:

    输出一行一个整数,表示小 F 在那一天所有可能的完成任务方式的歉意值之和对 998244353 取模的结果。

    思路:

    一开始写的时候,把时间复杂度的(2^20*2^20)算成了(2^21)成功T飞

    没T的那几个点也忘了取模……

    其实这道题只用组合数就好

    一个状态的贡献在于经过他有几种方案到达最终态

    所以我们可以发现,这是一个组合数问题

    比如说我们一共有5个任务,当前完成了3个任务

    那么转移到完成3个任务的情况有

    从00000转移到任选3个完成

    从有1个转移到有3个

    从有2个转移到有3个

    我们发现,由于我并不用确定到底选的是哪个

    只用考虑选了几个

    所以选i个的情况总数就是

    (原谅我直接搬了luogu的图)

    然后对于每种有贡献的情况分别考虑即可

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<bitset>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #define p 998244353
    #define rii register int i
    #define rij register int j
    #define int long long
    using namespace std;
    int zhs[55][55],n,m,opt[55],ans,c[25][25];
    void ycl()
    {
        c[0][0]=1;
        for(rii=1;i<=20;i++)
        {
            c[i][0]=1;
            for(rij=1;j<=20;j++)
            {
                c[i][j]=c[i-1][j-1]+c[i-1][j];
                c[i][j]%=p;
            }
        }
        opt[0]=1;
        for(rii=1;i<=20;i++)
        {
            for(rij=1;j<=i;j++)
            {
                opt[i]+=c[i][j]*opt[i-j];
                opt[i]%=p;
            }
        }
    }
    signed main()
    {
        scanf("%lld%lld",&n,&m);
        ycl();
        for(rii=1;i<=m;i++)
        {
            char ch=getchar();
            int zt=0,val;
            while(!isdigit(ch))
            {
                ch=getchar();
            }
            while(isdigit(ch))
            {
                zt+=ch-'0';
                ch=getchar();
            }
            scanf("%lld",&val);
            ans+=(((val*opt[zt])%p)*opt[n-zt])%p;
            ans%=p;
        }
        cout<<ans;
    }
  • 相关阅读:
    CodeForces 460B
    CodeForces 456A
    CodeForces462B
    HDU1394(线段树||树状数组)
    HDU1541(树状数组)
    HDU1556(树状数组)
    HDU5726(RMQ&&二分)
    POJ1182(并查集)
    HDU4496(并查集)
    HDU3038(并查集)
  • 原文地址:https://www.cnblogs.com/ztz11/p/9909686.html
Copyright © 2011-2022 走看看