AGC 041D

Wesley13
• 阅读 596

考虑限制一定是对于前缀和后缀的,并且显然相交的前后缀可以不考虑。然后还可以发现只用考虑最长的那一段的条件,即 $\lfloor\frac {n-1}{2}\rfloor$ 和 $\lfloor\frac {n-1}{2}\rfloor + 1$ 的长度。

可以将原序列分成两个部分。

如下: $$ {A A | (C) | B} $$ 我们把 $C$ 去掉,把最后一个 $A$ 提出来。

分别向前后差分分别记为数组 $a,b$ 。发现 $\sum _i (a_i + b_i) * i$ 就是除去 $A$ 的差。

即 $\text{最后一个 A 的值} > \sum _i (a_i + b_i) * i​$ 。

向后的差分还对 $A​$ 的最大值有影响,贡献要多一个。

并且容易发现最后的方案就是 $n - \sum (a_i + b_i)*i + \sum b_i​$, 小于 $0​$ 没有贡献。

然后发现有些时候方案数要多乘一个 $b_i+1$ (有一个 $C$ 在中间),这个也可以轻松统计。

代码

#include<bits/stdc++.h>
using namespace std;
int mod, n;
typedef long long ll;
int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
int sub(int a,int b){a-=b;return a<0?a+mod:a;}
int mul(int a,int b){return (ll)a*b%mod;}
int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
/* math */
const int N = 5010;
int f[2][N],g[2][N],h1[2][N],h2[2][N];

inline void Do1(int p,int i){
    for(int j=0;j<=n;j++)f[i][j] = g[i][j] = h1[i][j] = h2[i][j] = 0;
    for(int j=0;j<=n;j++){
        f[i][j] = add(f[i][j], f[i^1][j]);
        if(j>=p){
            f[i][j] = add(f[i][j], f[i][j-p]);
        }
    }
}
inline void Do2(int p,int i){
    for(int j=0;j<=n;j++)f[i][j] = g[i][j] = h1[i][j] = h2[i][j] = 0;
    for(int j=0;j<=n;j++){
        f[i][j] = add(f[i][j], f[i^1][j]);
        if(j>=p){
            f[i][j] = add(f[i][j], f[i][j-p]);
        }
    }
    for(int j=0;j<=n;j++){
        h1[i][j] = add(h1[i][j], 1ll*f[i^1][j]*(j/p-1)%mod);
        if(j>=p){
            h1[i][j] = add(h1[i][j], h1[i][j-p]);
        }
    }
    for(int j=0;j<=n;j++){
        f[i][j] = sub(mul(f[i][j], j/p),h1[i][j]);
    }
}

int main()
{
    cin >> n >> mod;
    int _d = (n-1)/2;
    bool flg=0;
    if(n%2==0){ flg=1; }
    int cur = 0;
    f[cur][0] = 1;
    for(int i=_d;i;i--){
        int p = i;
        Do1(p,cur^=1);
        if(i==_d && flg)Do2(p+1,cur^=1);
        else Do1(p+1,cur^=1);
    }
    int ans = 0;
    if(n==2){cout << 3 << endl;return 0;}
    for(int i=0;i<=n;i++){
        ans = add(ans, mul(f[cur][i], n-i));
    }
    cout << ans << endl;
}
点赞
收藏
评论区
推荐文章
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java 冒泡排序
思路1.将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;(第一轮结束后,序列最后一个元素一定是当前序列的最大值;)2.对序列当中剩下的n1个元素再次执行步骤1。3.对于长度为n的序列,一共需要执行n1轮比较时间复杂度最佳情况:T(n)O(n)最差情况:T(n)O(n2)平均情
Stella981 Stella981
3年前
Excel数据转化为sql脚本
在实际项目开发中,有时会遇到客户让我们把大量Excel数据导入数据库的情况。这时我们就可以通过将Excel数据转化为sql脚本来批量导入数据库。1在数据前插入一列单元格,用来拼写sql语句。 具体写法:"insertintot\_student(id,name,age,class)value("&B2&",'"&C2&"',"&D2&"
Stella981 Stella981
3年前
Spring boot在Docker中以JPA方式连接Mysql
背景最近在了解Docker的使用,发现docker在集群部署方面和运维方面有比较大的优势,通过统一的依赖关系,以镜像的方式,将已经打好包的镜像文件,部署到各个节点。如果不用考虑集群的同学,就不用折腾这个,如果想要让应用,有较强的快速部署的能力可以考虑考虑。目标在本机创建两个docker容器,分别为mysql的容器和springbo
Stella981 Stella981
3年前
HDU 2594(求最长公共前后缀 kmp)
题意是在所给的两个字符串中找最长的公共前后缀,即第一个字符串前缀和第二个字符串后缀的最长相等串。思路是将两个字符串拼接在一起,然后直接套用kmp算法即可。要注意用next会报编译错误,改成Next才过……但next确实不是c关键字。代码如下:!(https://oscimg.oschina.net/oscnet/5
Stella981 Stella981
3年前
Python递归函数、匿名函数、过滤函数
递归函数Python对递归的深度有限制,超过即会报错。所以一定一要注意跳出条件。斐波拉契数列一个数列,第一个数是1,第二个数也是1,从第三个数开始,每一个数是前两个数之和公式:f(1)1,f(2)1,f(3)f(1)f(2),...,f(n)f(n2)f(n1)
Wesley13 Wesley13
3年前
MySQL之索引(四)
压缩索引MyISAM使用前缀压缩来减少索引的大小,从而让更多的索引可以放入内存中,这在某些情况下能极大地提高性能。默认只压缩字符串,但通过参数设置也可以对整数做压缩。MyISAM压缩每个索引块的方法是,先完全保存索引块中的第一个值,然后将其他值和第一个值进行比较得到相同前缀的字节数和剩余的不同后缀部分,把这部分存储起来即可。例如,索引块中的第
Stella981 Stella981
3年前
LeetCode 5561. 获取生成数组中的最大值
文章目录1\.题目2\.解题1\.题目给你一个整数n。按下述规则生成一个长度为n1的数组nums:nums00nums11当2<2i<n时,nums2inumsi
Stella981 Stella981
3年前
ES中删除索引的mapping字段时应该考虑的点
1.创建新索引2.新索引创建新mapping3.原索引导出数据到新索引4.新索引创建原索引一致的别名5.删除原索引针对于第四步:这个就要用到索引别名了,如果你最开始建索引的时候没有考虑设计索引别名,那就杯具了。你可以把索引的名称设置成name\_v1 别名设置为name,然后代码里面访问搜索的时候连接的其实是别名na
Wesley13 Wesley13
3年前
Java程序如何不产生垃圾
应用程序如何可以不产生垃圾看上去很难想象,而且这个话题已经复杂到超出本文讨论的范畴,但是如果考虑以下几个方面可能会容易理解:JVM将内存分成两个部分来管理:堆和栈。这就是为什么当缺少内存时会有两个不同的错误(OutOfMemoryError和StackOverflowError)。栈内存只能被当前线程和当前执行的方法访问,因此,当线程离开当前执行