首页 > 其他分享 >ABC265F 题解

ABC265F 题解

时间:2024-07-27 16:51:06浏览次数:7  
标签:gs int 题解 sum return gets ABC265F dis

题面

\(O(nd^2)\)

考虑 \(f(i,j,k)\) 表示 dp 到第 \(i\) 维,距离 \(p,q\) 曼哈顿距离 \(j,k\) 的方案数。

考虑朴素转移:

设 \(dis=|p_{i+1}-q_{i+1}|\)。

\[\begin{aligned} f(i+1,j+t,k+dis-t)&\gets f(i,j,k)&(0\leq t\leq dis)\quad &(1)\\ f(i+1,j+d+t,k+t)&\gets f(i,j,k)&(t>0)\quad &(2)\\ f(i+1,j+t,k+d+t)&\gets f(i,j,k)&(t>0)\quad &(3)\\ \end{aligned} \]

但是复杂度是 \(O(nd^3)\) 的,优化一下应该可以做到 \(O((n+d)d^2)\)。无法通过。

注意到复杂度瓶颈在区间加,考虑差分优化:

令 \(gs(i,s,mn)\) 为 \(f(i,s-k,k)(k\geq mn)\) 的加法标记,\(g(i,d,mn)\) 为 \(f(i,k-d,k)(k\geq mn)\) 的加法标记。

于是原式改写为:

\[\begin{aligned} g(i,j,k)&=g(i,j,k)+g(i,j,k-1)\\ gs(i,j,k)&=gs(i,j,k)+gs(i,j,k-1)\\ f(i,j,k)&=gs(i,j+k,k)+g(i,j-k,k)\\ gs(i+1,j+k+dis,k)&\gets f(i,j,k)\\ gs(i+1,j+k+dis,k+dis+1)&\gets -f(i,j,k)\\ g(i+1,j+d-k,k+1)&\gets f(i,j,k)\\ g(i+1,j-d-k,k+1)&\gets f(i,j,k)\\ \end{aligned} \]

答案即为 \(\sum_{i=0}^d\sum_{j=0}^df(n,i,j)\)。

能过,但不够优秀?

\(O(n^2d)\)

我们考虑分开计数:

如果有 \(j\) 维的坐标在两点之间,即通过 \((1)\) 转移,\(n-j\) 维通过 \((2)(3)\) 转移,那么方案数就是两者之积。

注意到在两点之外对距离的贡献一定是 \(dis_p\gets t,dis_q\gets |p_i-q_i|+t\) 或相反。

先不考虑 \(t\)(超出部分),即在两点之外对距离的贡献是只给一边的距离加上 \(|p_i-q_i|\)。

通过简单 dp,可以求出 \((1)\) 的方案数:

令 \(f(i,j,k)\) 表示 dp 到第 \(i\) 维,有 \(j\) 维超出两点,到 \(p\) 的距离为 \(k\) 的方案数。

于是有转移:

\[\begin{aligned} f(i+1,j,k+t)&\gets f(i,j,k) &(0\le t\le dis)\\ f(i+1,j+1,k)&\gets f(i,j,k)\\ f(i+1,j+1,k+dis)&\gets f(i,j,k) \end{aligned} \]

差分优化即可。

考虑超出部分的计数:

设 \(sum=\sum_{i=1}^ndis_i\)。

则考虑枚举(dp 定义中的)\(j,k\),则剩余没用到的距离 \(ri=d-k,rj=d-sum+k\)。

继续枚举 \(T=\sum t\)(超出部分大小)是多少,根据插板法,可以把 \(T\) 非空分配到 \(j\) 维,于是有 \(\binom{T-1}{j-1}\) 种方案。

于是有 \(Ans=\left(\sum_{k=0}^df(n,0,k)\right)+\sum_{j=1}^n\sum_{k=0}^d\sum_{T=0}^{\min(ri,rj)}f(n,j,k)\dbinom{T-1}{j-1}\)。

\(O(nd^2)\),复杂度不对啊?考虑上指标求和。然后变成了:

\(Ans=\left(\sum_{k=0}^df(n,0,k)\right)+\sum_{j=1}^n\sum_{k=0}^df(n,j,k)\dbinom{T}{j}\)。

于是这里就不是瓶颈了。

复杂度 \(O(n^2d)\)。瓶颈在 dp。


\(O(nd^2)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 105, D = 1005, p = 998244353;
int f[2][D][D], a[N], b[N], n, d;
int g[2][D * 2][D], g2[2][D * 2][D];

inline int mod(int x) {return x >= p ? x - p : x;}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> n >> d;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i];
    g2[0][0][0] = 1;
    for(int i = 0; i <= n; i ++)
    {
        int i1 = i & 1, i2 = i1 ^ 1;
        memset(f[i2], 0, sizeof f[i2]);
        memset(g[i2], 0, sizeof g[i2]);
        memset(g2[i2], 0, sizeof g2[i2]);
        int dis = abs(a[i + 1] - b[i + 1]);
        for(int j = 0; j <= d; j ++)
        {
            for(int k = 0; k <= d; k ++)
            {
                f[i1][j][k] = mod(g2[i1][j + k][k] + g[i1][j - k + d][k]);
                if(j + k + dis <= d * 2)
                {
                    g2[i2][j + k + dis][k + 1] = mod(g2[i2][j + k + dis][k + 1] + f[i1][j][k]);
                    if(k + dis <= d) g2[i2][j + k + dis][k + dis] = mod(g2[i2][j + k + dis][k + dis] - f[i1][j][k] + p);
                }
                if(j + dis - k <= d) g[i2][j + dis - k + d][k] = mod(g[i2][j + dis - k + d][k] + f[i1][j][k]);
                if(j - dis - k >= -d && k + dis <= d) g[i2][j - dis - k + d][k + dis] = mod(g[i2][j - dis - k + d][k + dis] + f[i1][j][k]);
            }
        }
        for(int j = 0; j <= d * 2; j ++)
        for(int k = 1; k <= d; k ++)
        {
            g2[i2][j][k] = mod(g2[i2][j][k] + g2[i2][j][k - 1]);
            g[i2][j][k] = mod(g[i2][j][k] + g[i2][j][k - 1]);
        }
    }
    ll ans = 0;
    for(int i = 0; i <= d; i ++)
    for(int j = 0; j <= d; j ++)
        ans += f[n & 1][i][j];
    cout << ans % p;

    return 0;
}

\(O(n^2d)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1005, D = 1005, p = 998244353;
int a[N], b[N], n, d;
int f[2][N][D], g[2][N][D];

int fac[D], ifac[D];

ll qpow(ll a, ll b)
{
    if(!b) return 1;
    return ((b & 1) ? a : 1ll) * qpow(a * a % p, b >> 1) % p;
}

void init()
{
    fac[0] = ifac[0] = 1;
    for(int i = 1; i < D; i ++) fac[i] = 1ll * fac[i - 1] * i % p;
    ifac[D - 1] = qpow(fac[D - 1], p - 2);
    for(int i = D - 2; i >= 1; i --) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % p;
}

int C(int a, int b)
{
    if(a == b) return 1;
    if(a < 0 || b < 0 || a < b) return 0;
    return 1ll * fac[a] * ifac[b] % p * ifac[a - b] % p;
}

inline int mod(int x) {return x >= p ? x - p : x;}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    init();
    cin >> n >> d;
    int sum = 0;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i], sum += abs(a[i] - b[i]);
    
    g[1][0][0] = 1, g[1][0][1] = -1;
    // int cnt;
    for(int i = 1; i <= n + 1; i ++)
    {
        int i1 = i & 1, i2 = i1 ^ 1;
        memset(f[i2], 0, sizeof f[i2]);
        memset(g[i2], 0, sizeof g[i2]);
        int dis = abs(a[i] - b[i]);
        for(int j = 0; j <= i; j ++)
        for(int k = 0; k <= d; k ++)
        {
            if(k) g[i1][j][k] = mod(g[i1][j][k] + g[i1][j][k - 1]);
            f[i1][j][k] = mod(f[i1][j][k] + g[i1][j][k]);
            f[i2][j + 1][k] = mod(f[i2][j + 1][k] + f[i1][j][k]);
            if(k + dis <= d) f[i2][j + 1][k + dis] = mod(f[i2][j + 1][k + dis] + f[i1][j][k]);
            g[i2][j][k] = mod(g[i2][j][k] + f[i1][j][k]);
            if(k + dis <= d) g[i2][j][k + dis + 1] = mod(g[i2][j][k + dis + 1] - f[i1][j][k] + p);
            // cnt ++;
        }
    }
    // cerr << cnt;
    int ans = 0;
    for(int i = 0; i <= d; i ++)
        if(sum - i <= d)
            ans = (ans + f[(n + 1) & 1][0][i]) % p;
    for(int i = 1; i <= n; i ++)
    for(int j = 0; j <= d; j ++)
    {
        int ri = d - j, rj = d - sum + j;
        if(rj < 0 || rj > d) continue;
        int s = C(min(ri, rj), i);
        ans = (ans + 1ll * f[(n + 1) & 1][i][j] * s) % p;
    }
    cout << ans;

    return 0;
}

标签:gs,int,题解,sum,return,gets,ABC265F,dis
From: https://www.cnblogs.com/adam01/p/18327144

相关文章

  • 题解:CF1608F MEX counting
    题解:CF1608FMEXcounting与其他题解不同,本篇题解是运用辅助数组$g$来解决问题。虽然代码可能要繁琐一点,但是辅助数组的思路适用范围更广一点。首先还是转化为前$i$个数的$mex$在区间$[l_i,r_i]$内。我们用dp数组$f_{i,x,c}$表示处理到了第$i$个数,当前的mex为......
  • CF605E Intergalaxy Trips 题解
    Description\(n\)个点的有向完全图。\(i\toj\)的边每天出现的概率均为\(p_{i,j}\),若\(i=j\),有\(p_{i,j}=1\)。每天可以选择一条存在的出边走过去或停留在原地不动。求最优策略下从\(1\)到\(n\)的期望天数。\(n\le10^3\)。Solution设\(f_i\)表示\(i\)......
  • [题解]P2672 [NOIP2015 普及组] 推销员
    P2672[NOIP2015普及组]推销员为了便于操作,将住户信息按疲劳值从大到小排序。那么对于选\(X\)个住户,有\(2\)种情况:选疲劳值前\(X\)大的住户,答案即为\(\sum\limits_{i=1}^Xa[i]+2\times\max\limits_{i=1}^Xs[i]\)。选疲劳值前\(X-1\)大的住户,然后在剩下的住户中,距离比......
  • 《梦醒蝶飞:释放Excel函数与公式的力量》21.2 问题解决策略
     第21章:综合案例分析 21.2问题解决策略在综合案例分析中,解决问题的策略涉及多个步骤,从问题的识别、分析到实施解决方案和评估效果。通过系统的方法和多学科的知识,可以高效地解决复杂的问题。以下将介绍一个具体案例,并通过详细的步骤展示如何制定和实施问题解决策略。案例......
  • Codeforce 962 Div3 C~E 题解
    C题目大意​给定两个字符串a,b,q个询问,每次操作可以将a[i]赋值为任意一个字符,每次询问[l,r]区间内使得sorted(a[l,r])==sorted(b[l,r])的最小操作次数分析​ 不妨先考虑一个区间如何判断sorted后的字串是否相等,发现跟字符出现的次数有关,于是考虑前缀和预处理每一个26......
  • ABC273F Hammer 题解
    ABC273FHammer题解题目大意数轴上有\(n\)个锤子和\(n\)堵墙,第\(i\)个锤子位于\(x_i\),第\(i\)堵墙位于\(y_i\),第\(i\)个锤子可以对应的敲开第\(i\)堵墙。以原点为起点,给定终点\(t\),问最少移动多少个单位长度才能走到\(t\)。必须拿到对应锤子敲开墙才能走过这堵......
  • Codeforces Round 962 (Div. 3) 题解
    A.Legshttps://codeforces.com/contest/1996/problem/A翻译:农夫约翰的农场又迎来了美好的一天。农夫约翰来到农场后,数了数n条腿。众所周知,农场里只住着鸡和牛,一只鸡有2条腿,而一头牛有4条腿。假设约翰农场主数清了所有动物的腿,那么他的农场里最少有多少动物?思路求最少......
  • stata 代码实现熵值法计算 含常见问题解答
    适用:面板数据均可stata版本:无要求例如,使用了一个10年的省级面板数据,含15个指标,现在来计算各地区的熵值法得分。其中,x1x2x3x4x6x7x8x9x11x12x13x14x15是正向指标;而x5x10是负向指标。1.定义面板,定义指标的正负。tssetidyearglobalxlist1"x1x2x3x4x6x......
  • CF585F Digits of Number Pi 题解
    Description给定长度为\(n\)的数字串\(s\)和长度为\(d\)的不含前导零的数字串\(x,y(x\ley)\)。求存在长度至少为\(\left\lfloor\frac{d}{2}\right\rfloor\)的子串是\(s\)的子串的数字串\(t\in[x,y]\)的数量。\(n\le10^3\),\(d\le50\),答案对\(10^9+7\)取......
  • CF578E Walking! 题解
    Description给定一个长度为\(n\)的只包含L,R的字符串\(s\)。构造一个\(n\)排列\(p\)满足\(s[p_i]\nes[p_{i+1}](1\lei<n)\)。最小化\(p\)中\(p_i>p_{i+1}(1\lei<n)\)的数量。\(n\le10^5\),数据保证有解。Solution考虑把\(p\)中的每个极长连......