首页 > 其他分享 >[刷题笔记] Luogu P4933 大师

[刷题笔记] Luogu P4933 大师

时间:2023-08-23 21:22:25浏览次数:47  
标签:const 数字 int Luogu 公差 P4933 数组 include 刷题

Problem

Description

给定一个长度为 \(n\) 的数组 \(h\),你可以从中选取若干数字,使得你选择的数组组成一个等差数列。特别地,单一的数字和只有两个数字也算作等差数列。求你可选择的方案数。答案对 \(998244353\) 取模。

Analysis

考虑 \(f_{i,j}\) 表示前 \(i\) 个数,公差为 \(j\) 时的方案数。

特别地,公差允许是负数,直接作为数组下标会溢出,所以我们可以整体偏移,也就是使 \(j\) 加上一个很大的数字。

公差 \(j\) 可以不用枚举,只需要枚举 \(i\) ,对于每一个 \(i\),\(a_i-a_k(\forall k < i)\) 即为公差。需要注意必须是 \(a_i-a_k\) ,而不能是 \(a_k-a_i\)。

考虑转移,\(f_{i,a_i-a_k}+=f_{k,a_i-a_k}+1\)。直接拼接即可。不会少算,因为是 \(+=\),每次只在 \(a_k\) 的后面拼接。

那么我们的 \(answer\) 该如何计算呢?

我们显然不希望重复计算方案数。

如果每次加上更新完后的 \(f_{i,a_i-a_k}\) 显然会重复加很多,我们实际上每次只需要使 ans 加上 \(f_{k,a_i-a_k}+1\) 即可。显然 \(f_{i,a_i-a_k}\) 也是在这个基础上累加。这样就确保了每种情况只计算一遍。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int p = 10000;
const int N = 10100;
const int mod = 998244353;
int n;
int a[N];
int ans = 0;
int f[N][N*4];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
    {   
        cin>>a[i];
    }
    for(int i=1;i<=n;i++) 
    {
        for(int j=1;j<i;j++) //枚举公差
        {
            f[i][a[i]-a[j]+p] += f[j][a[i]-a[j]+p] + 1; //更新前 $i$ 位公差为 $a_i-a_j$ 的数量
            f[i][a[i]-a[j]+p] %= mod; 
            ans += f[j][a[i]-a[j]+p]+1; // ans +的一定不能是 $f_{i,a_i-a_j+p}$。若如此操作则会重复
            ans %= mod;
        }
    }
    cout<<ans+n<<endl;
    return 0;
}

标签:const,数字,int,Luogu,公差,P4933,数组,include,刷题
From: https://www.cnblogs.com/SXqwq/p/17652811.html

相关文章

  • [刷题笔记] Luogu P1064 [NOIP2006 提高组] 金明的预算方案
    ProblemAnalysis我们发现如果忽略主从关系,那这道题就是一个裸的01背包问题。主从关系处理也非常简单,借鉴P2014选课的经验,转换成树上背包问题。同理,本题是一个森林,若将0号节点参与建树的话就可以把森林转换成树,处理方便。具体地,设\(f_{i,j}\)表示以\(i\)为父节点,剩......
  • [刷题笔记] Luogu P2679 [NOIP2015 提高组] 子串
    ProblemDescription我们可以换个思路。从字符串\(A\)中拿出\(k\)个字串使其变成\(B\)。求有几种不同的方案?Analysis我们发现\(A\)中的一个字符取或者不取影响后面的决策,这并不代表它一定有后效性,我们可以记录这一层状态。和最长公共子序列同理,定义\(f_{i,j,k,l}(\fo......
  • 【刷题笔记】29. Divide Two Integers
    题目Giventwointegers dividend and divisor,dividetwointegerswithoutusingmultiplication,divisionandmodoperator.Returnthequotientafterdividing dividend by divisor.Theintegerdivisionshouldtruncatetowardzero.Example1:Input:dividen......
  • 【刷题笔记】28. Implement strStr()
    题目ImplementstrStr().Returntheindexofthefirstoccurrenceofneedleinhaystack,or-1ifneedleisnotpartofhaystack.Example1:Input:haystack="hello",needle="ll"Output:2Example2:Input:haystack="aaaaa&quo......
  • 【刷题笔记】27. Remove Element
    题目Givenanarraynumsandavalueval,removeallinstancesofthatvaluein-placeandreturnthenewlength.Donotallocateextraspaceforanotherarray,youmustdothisbymodifyingtheinputarrayin-placewithO(1)extramemory.Theorderofeleme......
  • 华为认证考试每日刷题与解析 Part4
    1、关于IGMPSnooping工作机制的描述,正确的是?A、二层交换机通过不断监听IGMP报文,在二层建立和维护PIM路由表B、没有运行IGMPSnooping时,组播报文将在二层广播:运行IGMPSnooping后,报文将不再在二层广播,而是进行二层组播C、如果主机发出IGMP离开报文时,交换机将该主机加入到相应......
  • [刷题笔记] [【LGR-155-Div.3】T4] Luogu P9572 「NnOI R2-T4」Colorful Days♪
    ProblemDescription有两个数组\(A,B\),我们可以将\(A\)数组无限次重复拼接。求最少需要多少次拼接使得拼接后的\(A,B\)的最长公共子序列最大。Analysis我们要学会从题目中找到一些信息,比如说本题的数据范围:对于\(100\%\)的数据,保证\(1\leqn,m,S_i,T_i\le10^6\),\(......
  • Luogu P1119 灾后重建
    在洛谷中查看解法1(我想的解法,不完全正确):很常见的套路:将询问按时间排序。时间复杂度:\(O(\;q\,(n\,logn+m)\;)\),即\(10^9\),开\(O2\)才能过。非常麻烦有没有,但我对拍的时候发现了一组数据很奇怪,待会给你们看看,我看看能不能hack#include<bits/stdc++.h>usingnamespacestd......
  • 刷题记录(四)
    攻防世界-wife_wife环境中有登陆和注册页面,注册界面有admin的选项,猜测此题需要伪造admin身份。以下是抓到数据包的内容:数据以json格式提交,该题的考点是Javascript的原型链污染。以下是该题服务端的关键代码:app.post('/register',(req,res)=>{letuser=JSON.parse......
  • 【刷题笔记】26. Remove Duplicates from Sorted Array
    题目Givenasortedarraynums,removetheduplicatesin-placesuchthateachelementappearonlyonceandreturnthenewlength.Donotallocateextraspaceforanotherarray,youmustdothisbymodifyingtheinputarrayin-placewithO(1)extramemory.E......