• 「P4996」「洛谷11月月赛」 咕咕咕(数论


    题目描述

    小 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 在那一天所有可能的完成所有任务方式的歉意值之和是多少。

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

    输入输出格式

    输入格式:

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

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    2 2
    00 1
    10 1
    输出样例#1: 复制
    4
    输入样例#2: 复制
    3 4
    000 16
    001 9
    110 4
    111 1
    输出样例#2: 复制
    260

    说明

    样例 1 解释:

    0-1串中第一个数字表示小 F 看没看比赛,第二个数字表示小 F 补没补锅。

    我们用∅ 表示小 F 什么都没干,AA 表示小 F 看了比赛,BB 表示小 F 补了锅,那么所有会产生愧疚的方式如下:

    :1
    {A}:1

    那么所有可能的选择如下:

    varnothing ightarrow{A} ightarrow{A,B}:2{A}{A,B}:2
    varnothing ightarrow{B} ightarrow{A,B}:1{B}{A,B}:1
    varnothing ightarrow{A,B}:1{A,B}:1

    所以答案是 2 + 1 + 1 = 42+1+1=4。

    数据范围

    保证出现的 mathrm{state}_istatei 互不相同。

    对于所有数据,有 1 leq n leq 201n20, 1 leq m leq min(2 ^ n, 10 ^ 5), 1 leq a_i leq 10 ^ 51mmin(2n,105),1ai105。

    题解 

    题意

    首先给定$m$个长为$n$的串,和踩中每个需付的代价。

    定义每次操作从$underbrace{000....00}_{n}$开始,每步可以任选至少一个$0$变成$1$,当所有串变成$underbrace{111....11}_{n}$时,操作结束。

    在操作过程中,如果在某时刻序列和之前给定的序列相同,那么要付给定序列的代价。

    问在这数不清的不同操作都做完之后(两次操作相同当且仅当变换过程完全相同),一共要付的代价,对$998244353$取模。


    哇这个题真实的难读懂啊qwq

    以下分析

    先来考虑对于一个给定串$s$,有多少个操作(设为$ans$)会撞上它。

    可以注意到,答案跟数字的位置无关,所以我们可以先把串抽象出来,数出有$c$个$1$,$(n-c)$个$0$。

    那么这$c$个$1$,可能是由$c-1$个$1$的串转移而来,可能是$c-2,c-3......0$个$1$的串转移而来。

    dp!

    设$f[i]$为转移成$i$个$1$的方案数。

    转移方程:$f[i]=sum_{j=0}^{j-1}(f[j]*C_{i}^{j})$。

    其中$C_i^j$是因为有$C_i^j$种方式从$j$个$1$转移成$i$个$1$。(在$i$个里面钦定$j$个为原有的$1$的方案数为$C_i^j$)

    那么从$000.....0$转移到$s$的方案数就为$f[c]$。

    而从$s$转移到$111.....1$的方案数可以倒着思考:从$111.....1$转移到$s$,有$(n-c)$个$1$变成了$0$对叭。

    所以可以直接操起求过的$f$数组,从$s$转移到全$1$串的方案数就为$f[n-c]$。

    然后用乘法原理乘起来,就得到了会经过串$s$的操作数,再乘上串$s$的单次代价就是这个串造成的总代价了。

    最后把$m$个串的代价加起来就是答案。

     1 /*
     2     qwerta 
     3     P4996 咕咕咕 Accepted 
     4     100
     5     代码 C++,0.6KB
     6     比赛 【LGR-055】洛谷11月月赛
     7     提交时间 2018-11-04 11:58:31//下考前几十秒发现自己忘开long long,太真实了qwq
     8     耗时/内存 108ms, 804KB
     9 */
    10 #include<iostream>
    11 #include<cstdio>
    12 using namespace std;
    13 #define LL long long//一年OI一场空,不开long long见祖宗
    14 const int mod=998244353;
    15 LL f[23];
    16 char s[23];
    17 LL je(int x)//返回x!(因为20!没爆long long就直接乱搞了
    18 {
    19     LL ans=1;
    20     while(x)
    21     {
    22         ans*=x;
    23         x--;
    24     }
    25     return ans;
    26 }
    27 LL C(int q,int w)//返回C(q,w)
    28 {
    29     return je(q)/je(w)/je(q-w);
    30 }
    31 int main()
    32 {
    33     ios::sync_with_stdio(false);
    34     int n,m;
    35     cin>>n>>m;
    36     f[0]=1;//初始化
    37     //先把f预处理出来
    38     for(int i=1;i<=n;++i)
    39     {
    40         for(int j=0;j<i;++j)
    41         {
    42             f[i]+=C(i,j)*f[j]%mod;
    43             f[i]%=mod;
    44         }
    45     }
    46     LL ans=0;
    47     for(int i=1;i<=m;++i)
    48     {
    49         cin>>s;
    50         int c=0;//c为s中1的个数
    51         for(int j=0;j<n;++j)
    52         c+=s[j]-'0';
    53         int v;//这个串的单次代价
    54         cin>>v;
    55         ans+=(LL)f[c]*f[n-c]%mod*v%mod;
    56         ans%=mod;
    57     }
    58     cout<<ans;
    59     return 0;
    60 }
  • 相关阅读:
    Python安装(小白教程)中文版Pycharm
    二叉树遍历1
    node* p 和 node *p 和 node * p 的区别
    WinForm中的ListBox组件编程
    C# winform listBox中的项上下移动(转)
    C# ListBox 左移、右移、上移、下移
    C#上移,下移TreeView中的树节点顺序
    C#遍历DataSet与DataSet元素实现代码
    C# 手动编写 DataSet,DataTable 及遍历DataSet中的数据
    【.NET】C#中遍历各类数据集合的方法
  • 原文地址:https://www.cnblogs.com/qwerta/p/9905335.html
Copyright © 2020-2023  润新知