[硫化铂]序排速快

2024-03-16 22:32
文章标签 硫化 序排 速快

本文主要是介绍[硫化铂]序排速快,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

序排速快

在这里插入图片描述
在这里插入图片描述

题解

首先,对于原题的分割点定义,我们可以实质上是可以把它看成两个点之间的一条线。
当该线的左边数的最大值小于右边数的最小值时该分割点会成立,也就是说,之后不会有任何一个冒泡排序的范围能跨越这道分割线。
事实上,如果我们直接去统计一个分割线的出现时间的话是对计算答案没什么效果,但我们可以发现我们可以从点的层面上计算答案。
一个相当经典的技巧,我们可以计算一个点被进行了冒泡排序多少次。
显然,当一个点两边的分割线都出现时,它的位置就已经被固定了,今后也不会再参与任何一次冒泡排序,对答案产生任何的贡献了。而再此前,它是会参与冒泡排序的。
我们考虑计算一个分割线会经过几次冒泡排序消失。
不妨记 p i p_i pi为权值不超过分割线 i i i的点最远的距离,显然 p i ⩾ i p_i\geqslant i pii,我们发现,一次冒泡排序,铁定会使 p i − 1 p_i-1 pi1,除非它已经变为 0 0 0,否则肯定会有点冲到它前面去。
于是,可以知道分割线 i i i的出现时间 t i = p i − i t_i=p_{i}-i ti=pii,那么一个排列的答案就是 ∑ i = 2 n max ⁡ ( t i − 1 , t i ) \sum_{i=2}^{n}\max(t_{i-1},t_{i}) i=2nmax(ti1,ti)

我们可以将原答案分为两种情况, t i − 1 ⩽ t i t_{i-1}\leqslant t_{i} ti1ti时,贡献 t i t_i ti;当 t i − 1 > t i t_{i-1}>t_i ti1>ti时,贡献 t i − 1 t_{i-1} ti1
可以发现,.
t i − 1 ⩽ t i ⇔ p i − 1 < p i t_{i-1}\leqslant t_{i}\Leftrightarrow p_{i-1}<p_i ti1tipi1<pi,即 i i i出现在 [ 1 , i − 1 ] [1,i-1] [1,i1]所有数的右边。
t i − 1 > t i ⇔ p i − 1 ⩾ p i t_{i-1}>t_i\Leftrightarrow p_{i-1}\geqslant p_i ti1>tipi1pi,即 [ 1 , i − 1 ] [1,i-1] [1,i1]中有一个数出现在 i i i右边。
枚举每个数的贡献,可以得到第一种情况的贡献,
s u m 1 = ∑ i = 1 n ∑ j = 1 i ( i − j ) ( i − 1 j − 1 ) ( j − 1 ) ! ( n − j ) ! sum_1=\sum_{i=1}^{n}\sum_{j=1}^{i} (i-j)\binom{i-1}{j-1}(j-1)!(n-j)! sum1=i=1nj=1i(ij)(j1i1)(j1)!(nj)!同理,可以得到第二种情况的贡献,
s u m 2 = ∑ i = 1 n ∑ j = 1 i ( i − j + 1 ) ( i − 1 j − 1 ) ( j − 1 ) ( j − 1 ) ! ( n − j ) ! sum_2=\sum_{i=1}^{n}\sum_{j=1}^{i} (i-j+1)\binom{i-1}{j-1}(j-1)(j-1)!(n-j)! sum2=i=1nj=1i(ij+1)(j1i1)(j1)(j1)!(nj)!将其相加,可以得到总答案,顺便改变一下 i , j i,j i,j的枚举顺序,
a n s = ∑ i = 1 n ∑ j = i n ( i j − j 2 + j − 1 ) ( j − 1 i − 1 ) ( i − 1 ) ! ( n − i ) ! ans=\sum_{i=1}^{n}\sum_{j=i}^{n}(ij-j^2+j-1)\binom{j-1}{i-1}(i-1)!(n-i)! ans=i=1nj=in(ijj2+j1)(i1j1)(i1)!(ni)!不妨将含 i i i的项与不含 i i i的项分开计算,那么有
a n s 1 = ∑ i = 1 n ∑ j = i n i j ( j − 1 ) ! ( i − 1 ) ! ( j − i ) ! ( i − 1 ) ! ( n − i ) ! = ∑ i = 1 n ∑ j = i n i ( n − i ) ! i ! j ! ( j − i ) ! i ! = ∑ i = 1 n i ( n − i ) ! i ! ∑ j = i n ( j i ) = ∑ i = 1 n i ( n − i ) ! i ! ( n + 1 i + 1 ) = ( n + 1 ) ! ∑ i = 1 n i i + 1 a n s 2 = ∑ i = 1 n ∑ j = i n ( − j 2 + j − 1 ) ( j − 1 i − 1 ) ( i − 1 ) ! ( n − i ) ! = ∑ i = 1 n ∑ j = i n ( − j 2 + j − 1 ) ( i − 1 ) ! ( n − i ) ! ( j − 1 ) ! ( i − 1 ) ! ( j − i ) ! = ∑ i = 1 n ∑ j = 1 i ( − i 2 + i − 1 ) ( i − 1 ) ! ( n − i ) ! ( n − j ) ! ( i − j ) ! ( n − i ) ! = ∑ i = 1 n ( − i 2 + i − 1 ) ( i − 1 ) ! ( n − i ) ! ∑ j = 1 i ( n − j n − i ) = ∑ i = 1 n ( − i 2 + i − 1 ) ( i − 1 ) ! ( n − i ) ! ( n i ) = n ! ∑ i = 1 n − i 2 + i − 1 i ans_1=\sum_{i=1}^n\sum_{j=i}^nij\frac{(j-1)!}{(i-1)!(j-i)!}(i-1)!(n-i)!=\sum_{i=1}^n\sum_{j=i}^ni(n-i)!i!\frac{j!}{(j-i)!i!}\\ =\sum_{i=1}^ni(n-i)!i!\sum_{j=i}^n\binom{j}{i}=\sum_{i=1}^ni(n-i)!i!\binom{n+1}{i+1}=(n+1)!\sum_{i=1}^n\frac{i}{i+1}\\ ans_2=\sum_{i=1}^n\sum_{j=i}^n(-j^2+j-1)\binom{j-1}{i-1}(i-1)!(n-i)!=\sum_{i=1}^n\sum_{j=i}^n(-j^2+j-1)(i-1)!(n-i)!\frac{(j-1)!}{(i-1)!(j-i)!}\\ =\sum_{i=1}^n\sum_{j=1}^i(-i^2+i-1)(i-1)!(n-i)!\frac{(n-j)!}{(i-j)!(n-i)!}=\sum_{i=1}^n(-i^2+i-1)(i-1)!(n-i)!\sum_{j=1}^i\binom{n-j}{n-i}\\ =\sum_{i=1}^n(-i^2+i-1)(i-1)!(n-i)!\binom{n}{i}=n!\sum_{i=1}^n\frac{-i^2+i-1}{i} ans1=i=1nj=inij(i1)!(ji)!(j1)!(i1)!(ni)!=i=1nj=ini(ni)!i!(ji)!i!j!=i=1ni(ni)!i!j=in(ij)=i=1ni(ni)!i!(i+1n+1)=(n+1)!i=1ni+1ians2=i=1nj=in(j2+j1)(i1j1)(i1)!(ni)!=i=1nj=in(j2+j1)(i1)!(ni)!(i1)!(ji)!(j1)!=i=1nj=1i(i2+i1)(i1)!(ni)!(ij)!(ni)!(nj)!=i=1n(i2+i1)(i1)!(ni)!j=1i(ninj)=i=1n(i2+i1)(i1)!(ni)!(in)=n!i=1nii2+i1显然,上面这两者都是可以线性递推求解的,于是我们只需要预处理一下阶乘与逆元就可以快速计算 n ∈ [ L , R ] n\in[L,R] n[L,R]中的所有情况了。

时间复杂度 O ( R ) O\left(R\right) O(R)

源码

这还需要贴吗?

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10000005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL; 
typedef long double ld;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;
const int mo=998244353;
const int mod=1e5+3;
const int inv2=5e8+4;
const int jzm=2333;
const int zero=2000;
const int n1=1000;
const int M=100000;
const int orG=3,ivG=332748118;
const long double Pi=acos(-1.0);
const double eps=1e-12;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*t*a%p;a=1ll*a*a%p;s>>=1;}return t;}
int n,L,R,fac[MAXN],inv[MAXN],ff[MAXN],answer;
void init(){fac[0]=fac[1]=inv[0]=inv[1]=ff[1]=1;for(int i=2;i<=R+1;i++)fac[i]=1ll*i*fac[i-1]%mo,ff[i]=1ll*(mo-mo/i)*ff[mo%i]%mo,inv[i]=1ll*ff[i]*inv[i-1]%mo;
}
int C(int x,int y){if(x<0||y<0||x<y)return 0;return 1ll*fac[x]*inv[y]%mo*inv[x-y]%mo;
}
signed main(){//freopen("tros.in","r",stdin);//freopen("tros.out","w",stdout);read(L);read(R);init();int sum1=0,sum2=0;for(int i=1;i<=R;i++){Add(sum1,1ll*i*ff[i+1]%mo,mo);Add(sum2,1ll*add(i-1,mo-1ll*i*i%mo,mo)*ff[i]%mo,mo);int ans=add(1ll*fac[i+1]*sum1%mo,1ll*fac[i]*sum2%mo,mo);if(i>=L)answer^=ans;}printf("%d\n",answer);return 0;
}

谢谢!!!

这篇关于[硫化铂]序排速快的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/816934

相关文章

电子元器件选型(二):防硫化电阻

一、电阻硫化         贴片电阻的内部电极采用了银 (Ag),如果有硫黄成分气体从保护膜和电镀层之间的缝隙侵入,就会发生硫化反应,慢慢地生成硫化银 ()。由于硫化银不导电,所以随着电阻被硫化,电阻值逐渐增大,直至最终成为开路。电阻硫化之后,在电阻的电极内侧表面出现硫化银结晶。         银由于优质的导电特性,会被使用作为电极、焊接材料、电接触材料,所以在电子元器件中大量使用

[硫化铂]开心消消乐

开心消消乐 题目概述 题解 首先很容易联想到 Gym 102586J 于是我们自然而然可以想到通过建立一个dfa来处理。 但显然,我们这个dfa怎么建才是关键。 我们观察到我们每次是将三个连续的字符脱水缩合成一个字符,事实上我们每次可以将前面的两个字符当成一个函数,而最后一位当作传入函数的参数。 实际上, 我们发现,我们的每次操作相当于以最后一个数作为参数,将前面的函数不断嵌套。 而

[硫化铂]好

乐 题目概述 题解 首先, O neInDark \text\color{black}{O}\color{red}{neInDark} OneInDark:对于这种每次删一个连续段的问题,我们应该很容易想到区间dp。 首先,我们可以发现合法的连续段是呈现一个单峰的态势,即只存在一个点比 旁边的两个点都高,其它的都是在两个点的中点处。 我们可以定义 d p l , r dp_{l,r}

[硫化铂]传染

传染 题目描述 题解 可以发现,我们可以将原题转化成在一张图上选几个点,使之可以覆盖整个图。 每个点可以向与它距离不超过 r i r_i ri​的点连一条单向边,使得我们选的所有点可以到达图上任意一个点。 那么我们显然可以直接将这个图建出来,然后观察一下这个图。 首先,对于一个边双联通分量中,显然任意两个点都是可以互相覆盖的,所以一个边双联通分量中最多选择一个点,我们不妨先缩一下点。

[硫化铂]密码

密码 题解 完了,居然开始阴间的密码题了。 首先的第一个想法是像 D N A DNA DNA片段一样,加几个开始码,结束码用于识别。但显然,这最多只能拿前面的 55 p t s 55pts 55pts,我们的正解最多只给我们 50 50 50个空位,显然是不行的。 这个时候,我们就可以联想到我们传统的线性变换方法用于加密了,由于我们给定的是加密串中的 k k k个位置与整个原文串,我们得

[硫化铂]膜拜大丹

膜拜大丹 题解 首先我们可以观察到一个性质,我们一定只会走二元环。 整张图是一个二分图,我们每次是从一边跳到另一边,所以走过的路径一定是一个偶环。 我们不妨记我们走过的路径为 A p 1 → B q 1 → A p 2 → B q 2 → . . . → B q n → A p n + 1 A_{p_1}\rightarrow B_{q_1}\rightarrow A_{p_2}\rig

[硫化铂]守序划分问题

守序划分问题 题目大意 题解 Province Team Selection=PTS=PtS=硫化铂,所以就叫这段时间的模拟赛题硫化铂吧。 结论题,我竟然没有想到 首先,既然是结论题,那么有结论,如果我们的一种划分所有集合方案使得 min ⁡ i ∈ S A i ⩾ max ⁡ i ∉ S A i \min_{i\in S}A_i\geqslant\max_{i\not \in S

【字符串】【分类讨论】【KMP】1163. 按字典序排在最后的子串

作者推荐 视频算法专题 本文涉及知识点 字符串 字典序 分类讨论 本题无法使用KMP,因为t1不段变化。 LeetCode1163. 按字典序排在最后的子串 给你一个字符串 s ,找出它的所有子串并按字典序排列,返回排在最后的那个子串。 示例 1: 输入:s = “abab” 输出:“bab” 解释:我们可以找出 7 个子串 [“a”, “ab”, “aba”, “abab”, “b”,

二硫化钨/二硒化钨纳米复合材料|WSe2二硒化钨负载掺氮三维石墨烯|氮掺杂二氧化钛负载二硒化钨|二硒化钨薄片/氧化铟纳米线复合材料

二硫化钨/二硒化钨纳米复合材料|WSe2二硒化钨负载掺氮三维石墨烯|氮掺杂二氧化钛负载二硒化钨|二硒化钨薄片/氧化铟纳米线复合材料 二硫化钨/二硒化钨纳米复合材料 二维过渡金属硫族化合物(2D-TMDCs)具有独特的层状结构,可调的直接带隙、较好的柔韧性和高透光性等,在固体纳米器件、光电子器件、可穿戴设备、传感及功能薄膜等领域前景广阔。然而,如何高效的制备高品质大面积的2D-TMDCs材料一直

康托展开,求某个排列在字典序排的位置

遇到一个编程题,考核的内容就是康托展开问题,这里就重新描述下 X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!。这就是康托展开。康托展开可用代码实现。推导过程大家有兴趣可以自己去找资料,这里我就直接