zoukankan      html  css  js  c++  java
  • UOJ182 a^1 + b problem 解题报告

    题目描述

    有一个长度为\(n(n\le 10^5)\)的数列,在模\(M\)意义下进行\(m(m \le50000)\)次操作,每次操作形如以下两种形式:

    1 \(x\) 表示每个数加\(x(0 \le x<M)\);

    2 表示每个数对模数\(M\)取逆元,保证逆元存在。

    输出每次操作后所有数的和,对\(M\)取模。这里\(M=998244353\)。

    简要题解

    设原始数列为\(x_i\)。对于一个初始的数\(x\),经过第i个操作后一定可以写成\(\dfrac {a_i \times x+b_i} {c_i \times x+d_i}\)的形式。先用线性时间求出参量\(a_i,b_i,c_i,d_i\),于是问题转化为对每个\(i\),求出\(\displaystyle \sum\limits_{j = 1}^n {\frac{{{a_i}{x_j} + {b_i}}}{{{c_i}x_j + {d_i}}}} \)。先将整数提取出来,只需考虑\(\displaystyle \sum\limits_{j = 1}^n {\frac{{e_i}}{{{c_i}x_j + {d_i}}}} \)。

    (1)若\(c_i=0\),则直接计算即可;

    (2)否则,对每个\(i\)可以归一化为求\(\displaystyle \sum\limits_{j = 1}^n {\frac{{{1}}}{{{x_j} + {t_i}}}} \)。

    将分母通分,则转化为\(\dfrac {P(t_i)} {Q(t_i)}\),其中\(P,Q\)为\(t_i\)的不超过\(n\)次多项式。

    这里\(Q(x)=(x+x_1) \cdots (x+x_n)\)。考虑如何快速求出\(P\)。不难发现\(P\)正是\(Q\)的导数。

    于是问题转化成了多点求值问题。可在\(O(n(\log n)^2+m(\log m)^2)\)时间复杂度求解。

    还应注意到不会出现\(P(t_i)=Q(t_i)=0\)的情况,因为根据洛必达法则,此时极限趋于无穷大,不会是有限值,而题目保证了逆元存在。

    说明

    最近看了大量多项式应用的问题,绝大多数都是多项式逆元,这是见到的第一道应用多项式的多点求值的问题(非裸题),搞明白后不禁感叹:好题啊!佩服出题人系列。

    核心代码

     1 int x[100001], y[60001], w[60001], k[60001];
     2 int ans1[60001], ans2[60001];
     3 int main()
     4 {
     5     int n, m, op, t, sum = 0;
     6     scanf("%d%d", &n, &m);
     7     for (int i = 0; i < n; i++){
     8         scanf("%d", &x[i]);
     9         sum = add(sum, x[i]);
    10         x[i] = -x[i];
    11     }
    12     vector<Poly> v(262144);
    13     mulInit(1, n, x, v);
    14     Poly q = v[1], p = diff(q);
    15     int a = 1, b = 0, c = 0, d = 1, cnt = 0;
    16     for (int i = 0; i < m; i++){
    17         scanf("%d", &op);
    18         if (op == 1){
    19             scanf("%d", &t);
    20             a = add(a, mul(t, c));
    21             b = add(b, mul(t, d));
    22         }
    23         else{ swap(a, c); swap(b, d); }
    24         if (c){
    25             int t = power(c, MOD - 2);
    26             w[i] = mul(mul(a, t), n);
    27             k[i] = mul(sub(b, mul(a, mul(d, t))), t);
    28             y[cnt++] = mul(d, t);
    29         }
    30         else{
    31             int t = power(d, MOD - 2);
    32             w[i] = mul(add(mul(a, sum), mul(b, n)), t);
    33             k[i] = -1;
    34         }
    35     }
    36     mulInit(1, cnt, y, v);
    37     getVal(1, cnt, p, v, ans1);
    38     getVal(1, cnt, q, v, ans2);
    39     for (int i = 0, j = 0; i < m; i++){
    40         if (k[i] == -1)printf("%d\n", w[i]);
    41         else{
    42             int t = mul(ans1[j], power(ans2[j], MOD - 2));
    43             printf("%d\n", add(w[i], mul(k[i], t)));
    44             j++;
    45         }
    46     }
    47 }
  • 相关阅读:
    SmartJS 第一期(0.1)发布
    smartJS 0.1 API 讲解
    smartJS 0.1 API 讲解
    20160113006 asp.net实现ftp上传代码(解决大文件上传问题)
    20151224001 GridView 多按钮的各种使用方法
    20151221001 GridView 模板
    20151218001 雕爷自白:我为什么非要这么干
    20151210001 DataGridView 选中与被选中
    20151126001 网页中嵌入谷歌动态地图
    20151125001 询问对话框 中的文字换行
  • 原文地址:https://www.cnblogs.com/zbh2047/p/8569928.html
Copyright © 2011-2022 走看看