杭电多校第5场补题 G - permutation 2

本文探讨了一种算法,用于计算在特定条件下,从1到N的全排列数量。条件包括首项为x,末项为y,且任意两项差值不超过2。文章通过实例解释了算法的思路,并提供了C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You are given three positive integers N,x,y
Please calculate how many permutations of 1∼N satisfies the following conditions (We denote the i-th number of a permutation by pi): 

1. p1=x 

2. pN=y

3. for all 1≤i<N, |pi−pi+1|≤2

题意:

给你一个N,x,y,分别是元素的个数(元素从1~N),首项,末项。现在问你首项是x,末项是y,并且是1~N的全排列的排列数是多少。该排列中每相邻两个元素的差值不大于2。

Input

The first line contains one integer T denoting the number of tests. 

For each test, there is one line containing three integers N,x,y

* 1≤T≤5000

* 2≤N≤10^5

* 1≤x<y≤N

Output

For each test, output one integer in a single line indicating the answer modulo 998244353.

Sample Input

3
4 1 4
4 2 4
100000 514 51144

Sample Output

2
1
253604680

思路:

1.首先,因为相邻元素的差值不大于2,下一个元素必须由该元素+1、+2、-1、-2而来。

2.x是首项,y是末项,排列是1~N 的全排列之一,如果x不是1,y不是N,我们要考虑到两种大体上的走法

   x->1->N或者x->N->1 ,  再考虑到y是末项,所以 应该是  x  ->  1  ->  x+1  ->  y-1  ->  N  ->  y

为什么会有x+1和y-1呢?因为x需要走到1再走回来,所以新起点是x+1,而y是末项,所以我们得从x+1走到y-1,这之间的元素都得走一遍,再走到N再回到y

3.因为下一个元素的差距不会超过2,所以如果你想从x->y再回来,那么必须从x开始2个2个的走到y+1或y-1,再2个2个的走回来,不然是走不回来的,走回来之后就走不回去了,这决定了x->1->x+1 和 y-1->N->y只有一种走法,那么答案就是x+1 -> y-1的走法了

4.根据2,x+1 -> y-1之间每走1步跳过的元素必须都要走一遍,因为这一段不能走回来,否则末项就不会是y了。所以有两种走法,比如说:5,要到5,可以是4走1个到5,也可以是2先走2个到4,再回走1个到3,再走2个到5,只有这两种走法。

因此,我们只要算出x+1到y-1之间要有几步(step,或者说转化成从1走到e-s+1),step由两种走法组成的方法有几种,就是答案

一开始我是把step的两种方法排列组合得到答案,发现要么会超时,要么预处理数组太大,开不出来,后来看了别人的代码,直接预处理dp得到答案,dp[n]=dp[n-1]+dp[n-3];

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 1e5+5;
const int mod = 998244353 ;
ll dp[MAX];
int main(){
	int t;
	scanf("%d",&t);
	dp[1]=dp[2]=dp[3]=1;
	for(int i=4;i<MAX;i++){
		dp[i]=(dp[i-1]+dp[i-3])%mod;
	}
	while(t--){
		int N,x,y;
		scanf("%d%d%d",&N,&x,&y);
		int s=x,e=y;
		if(x!=1) s+=1;
		if(y!=N) e-=1;
		int step=e-s+1;
		printf("%lld\n",dp[step]);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值