首页 > 其他分享 >CF1948F 题解

CF1948F 题解

时间:2024-03-16 11:12:53浏览次数:22  
标签:ModLL CF1948F return 题解 res ModInt out OP

对于每个询问,可以把这 \(r - l + 1\) 个袋子包合并成一个 有 \(\sum\limits_{i = l}^r a_i\) 个金币和 \(\sum\limits_{i = l}^r b_i\) 个银币的袋子。\([l, r]\) 外的袋子同理也可以这样合并。

假设 \(sum_a = \sum\limits_{i = 1}^n a_i, sum_b = \sum\limits_{i = 1}^n b_i\),\(in_a = \sum\limits_{i = l}^r a_i, in_b = \sum\limits_{l = 1}^r b_i\), \(out_a = sum_a - in_a, out_b = sum_b - in_b\)。

那么原问题就是查询 \(in_a + rand(in_b) > out_a + rand(out_b)\) 的概率,其中 \(rand(x)\) 表示 \(x\) 个银币时的随机取值。把上面的式子中符号两边的 \(rand\) 移到同一边,得到:

\[rand(in_b) - rand(out_b) > out_a - in_a \]

观察到 \(in_b + out_b = sum_b\),那么尝试把 \(rand(in_b) - rand(out_b)\) 变成 \(rand(in_b) + rand(out_b)\)。只需两边同时加上 \(out_b\),式子变成:

\[rand(in_b) + rand(out_b) > out_a + out_b - in_a \]

接着又有 \(rand(in_b) + rand(out_b) = rand(in_b + out_b) = rand(sum_b)\),所以最终转化成了:

\[rand(sum_b) > out_a + out_b - in_a \]

其中 \(out_a + out_b - in_a\) 是可以 \(\Theta(1)\) 求得的,设 \(Q = out_a + out_b - in_a\),那么答案是:

\[\sum\limits_{x = Q + 1}^{sum_b} \binom{sum_b}{x} \times \left(\frac{1}{2}\right)^{n} \]

预处理组合数后缀和即可,复杂度为 \(O(n)\)。

code:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const int N = 2E6 + 5;
template <class T>
T power(T a, long long b) {
  T res = 1;
  for (; b; b >>= 1, a *= a) {
    if (b & 1)
      res *= a;
  } return res;
}
#define C constexpr
#define FC friend constexpr
#define OP operator
template <long long mod>
class ModLL {
  public:
    long long n;
    static long long Mod;
    C ModLL() : n{} {}
    C ModLL(long long x) : n(norm(x % getmod())) {}
    C long long norm(long long x) {
      if (x >= getmod()) x %= getmod();
      if (x <= -getmod()) x %= getmod();
      if (x < 0) x += getmod();
      return x;
    }
    C long long getmod() {return (mod > 0 ? mod : Mod);}
    explicit C OP long long() const {return n;}
    C ModLL OP -() const {ModLL a; a.n = norm(getmod() - n); return a;}
    C ModLL inv() {assert(n != 0); return power((*this), getmod() - 2);}
    C ModLL &OP += (ModLL w) & {n = norm( n + w.n); return (*this);}
    C ModLL &OP -= (ModLL w) & {n = norm( n - w.n); return (*this);}
    C ModLL &OP *= (ModLL w) & {n = norm( 1LL * n * w.n % getmod()); return (*this);}
    C ModLL &OP /= (ModLL w) & {return (*this) *= w.inv();}
    FC ModLL OP + (ModLL a, ModLL b) {ModLL res = a; res += b; return res;}
    FC ModLL OP - (ModLL a, ModLL b) {ModLL res = a; res -= b; return res;}
    FC ModLL OP * (ModLL a, ModLL b) {ModLL res = a; res *= b; return res;}
    FC ModLL OP / (ModLL a, ModLL b) {ModLL res = a; res /= b; return res;}
    FC bool OP == (ModLL a, ModLL b) {return (a.n == b.n);}
    FC bool OP != (ModLL a, ModLL b) {return (a.n != b.n);}
    FC istream &OP >> (istream &is, ModLL &a) {
      long long x = 0; is >> x;
      a = ModLL(x); return is;
    }
    FC ostream &OP << (ostream &os, const ModLL &a) {return (os << (a.n));}
} ; 
template <int mod>
class ModInt {
  public:
    int n;
    static int Mod;
    C ModInt() : n{} {}
    C ModInt(int x) : n(norm(x % getmod())) {}
    C int norm(int x) {
      if (x >= getmod()) x %= getmod();
      if (x <= -getmod()) x %= getmod();
      if (x < 0) x += getmod();
      return x;
    }
    C static int getmod() {return (mod > 0 ? mod : Mod);}
    explicit C OP int() const {return n;}
    C ModInt OP -() const {ModInt a; a.n = norm(getmod() - n); return a;}
    C ModInt inv() const {assert(n != 0); return power((*this), getmod() - 2);}
    C ModInt &OP += (ModInt w) & {n = norm( n + w.n); return (*this);}
    C ModInt &OP -= (ModInt w) & {n = norm( n - w.n); return (*this);}
    C ModInt &OP *= (ModInt w) & {n = norm( 1LL * n * w.n % getmod()); return (*this);}
    C ModInt &OP /= (ModInt w) & {return (*this) *= w.inv();}
    FC ModInt OP + (ModInt a, ModInt b) {ModInt res = a; res += b; return res;}
    FC ModInt OP - (ModInt a, ModInt b) {ModInt res = a; res -= b; return res;}
    FC ModInt OP * (ModInt a, ModInt b) {ModInt res = a; res *= b; return res;}
    FC ModInt OP / (ModInt a, ModInt b) {ModInt res = a; res /= b; return res;}
    FC bool OP == (ModInt a, ModInt b) {return (a.n == b.n);}
    FC bool OP != (ModInt a, ModInt b) {return (a.n != b.n);}
    FC istream &OP >> (istream &is, ModInt &a) {
      int x = 0; is >> x;
      a = ModInt(x); return is;
    }
    FC ostream &OP << (ostream &os, const ModInt &a) {return (os << (a.n));}
} ; 
template <>
long long ModLL <0> :: Mod = (long long)(1E18) + 9;
template <>
int ModInt <0> :: Mod = 998244353;
using P = ModInt <998244353>;
#undef C
#undef FC
#undef OP
signed main(void) {
  ios :: sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  int n, q; cin >> n >> q;
  vector <int> a(n + 1), b(n + 1);
  for (int i = 1; i <= n; ++i) cin >> a[i];
  for (int i = 1; i <= n; ++i) cin >> b[i];
  vector <int> suma(n + 1), sumb(n + 1);
  for (int i = 1; i <= n; ++i) {
    suma[i] = suma[i - 1] + a[i];
    sumb[i] = sumb[i - 1] + b[i];
  }
  vector <P> comb(sumb[n] + 1), fac(sumb[n] + 1); fac[0] = 1;
  for (int i = 1; i <= sumb[n]; ++i) fac[i] = fac[i - 1] * i;
  comb[sumb[n]] = 1;
  for (int i = sumb[n] - 1; i >= 0; --i) 
    comb[i] = comb[i + 1] + (fac[sumb[n]] / fac[i] / fac[sumb[n] - i]);
  P div = power(P(2), sumb[n]);
  for (int i = 1; i <= q; ++i) {
    int l, r; cin >> l >> r;
    --l;
    int in_a = suma[r] - suma[l], in_b = sumb[r] - sumb[l];
    int out_a = suma[n] - in_a, out_b = sumb[n] - in_b;
    int Q = out_a + out_b - in_a;
    if (Q >= sumb[n]) cout << 0 << ' ';
    else if (Q < 0) cout << 1 << ' ';
    else cout << comb[Q + 1] / div << ' ';
  }
  return 0;
}

标签:ModLL,CF1948F,return,题解,res,ModInt,out,OP
From: https://www.cnblogs.com/CTHOOH/p/18076821

相关文章

  • CF145C Lucky Subsequence 题解
    首先,我们对这个幸运数进行分析,发现:\(10^9\)以内只有\(1023\)个幸运数,即\(\sum\limits_{i=0}^92^i\)个。考虑对幸运数和非幸运数分类讨论。幸运数部分:01背包裸题,\(dp_{i,j}\)表示前\(i\)个幸运数里选了\(j\)个,转移方程为\(dp_{i,j}=dp_{i-1,j}+dp_{i-1,j-1}\tim......
  • [HNOI2012] 矿场搭建 题解
    [HNOI2012]矿场搭建前置知识:#Tarjan求点双连通分量题目大意​ 给你一张无向连通图,任意删去其中一个点,要求在删点后在每个连通块中有一个点被选择,问至少需要选择多少个点,以及选择的方案数。输入输出格式输入​ 多组数据以\(N=0\)结束​ 每组数据第一行为边的数量\(N\(N......
  • NOI2021 轻重边 题解
    NOI2021轻重边题目链接:#4812.[NOI2021]轻重边前置知识:#树链剖分#线段树题目大意给定\(n\)个点组成的树,\(m\)次操作。修改操作会让路径\(a\tob\)上的所有点的所有连边对答案的贡献变为\(0\),路径\(a\tob\)的所有边的贡献变为\(1\);查询操作则统计路径\(a\tob\)的......
  • CF57C Array 题解
    发现单调不降序列反过来就是单调不增序列,只需考虑单调不降序列即可。假如将问题转化为:初始为\(1\),一共有\(n+1\)个位置,有\(n-1\)次增加答案的机会,每个位置可以拥有多次增加答案的机会,问一共有多少种可能性。显然答案为\(C_{2n-1}^{n-1}\)。所以总体答案为\(2C_{2n-1}^{n-......
  • P2824 [HEOI2016/TJOI2016] 排序 与 ABC297_g Range Sort Query 题解
    洛谷题目链接:排序abc题目链接:Atcoder或者洛谷两道差不多的题拿出来说说。本题有双\(\log\)做法,也有单\(\log\)做法,都讲讲。双\(\log\)做法对于第一个题而言,询问最终\(pos\)位置上的数为多少,那么这个问题是否具有单调性?这个是很有意思的点,我们考虑只关注某个数\(x\)......
  • 洛谷题解 - B3850 [GESP202306 四级] 幸运数
    目录题目描述输入格式输出格式样例#1样例输入#1样例输出#1代码题目描述小明发明了一种“幸运数”。一个正整数,其偶数位不变(个位为第111位,十位为第......
  • 炸弹题解
    这题有两种做法,一种tarjan,一种逆天DP用lower_bound或upper查找i所在范围的左右边界对应下标普通Tarjan+缩点#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=5e5+10,mod=1e9+7;intn,dfn[N],low[N],head2[N],num,cnt,head[N],belong[N];b......
  • 【PR #12】划分序列 / Yet Another Mex Problem 题解
    题目链接题目大意给定一个长度为\(n\)的序列\(a\),定义一段区间的价值为该区间的\(\operatorname{mex}\)乘上区间元素总和。你需要将序列划分成若干个长度\(\leqk\)的区间。一个划分方案的价值为划分出来的每个区间价值之和,求所有划分方案的价值最大值。\(1\leqk\le......
  • centos6使用yum网络源失败,问题解决
    在进行测试环境部署时,需要用到yum安装一些软件包,目前服务器是通外网的,所以这里我就直接使用的网络源进行yum下载的令我惊讶的是用yum命令安装居然失败了!!!以下是我的排查到解决的心路历程:1.首先执行命令yumlist查看发现报错如下:从报错信息来看是说无法连接到http(s),ftp的......
  • CF575H Bots 题解 组合数学
    Bots传送门SashaandIraaretwobestfriends.Buttheyaren’tjustfriends,theyaresoftwareengineersandexpertsinartificialintelligence.Theyaredevelopinganalgorithmfortwobotsplayingatwo-playergame.Thegameiscooperativeandturn......