列表

详情


NC218401. 小G的排列

描述

题目中设p1,p2,…,pn是1,2,…,n的一个排列。
如果该排列的一个连续子段pl,pl+1,…,pr满足相邻两项的差的绝对值为1, 
则说它是一个好的子段。现已知任意好的子段的长度均不超过m. 
求满足该条件的排列数,对10^9+7取模。

输入描述

样例会给出一行输入两个整数代表n,m

输出描述

请输出所有满足该条件的排列数,需要答案对10^9+7取模。

示例1

输入:

5 2

输出:

92

示例2

输入:

3 1

输出:

0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 234ms, 内存消耗: 572K, 提交时间: 2021-02-26 21:08:02

#include<cstdio>
using namespace std;
template<class T>inline void read(T&a)
{char c=getchar();int f=1;a=0;while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c<='9'&&c>='0') a=(a<<1)+(a<<3)+c-48,c=getchar();a*=f;}
template<class T>void write(T a){if(a<0) putchar('-'),a=-a;if(a>9) write(a/10);putchar(a%10+48);}
const int o=1e4+10,MOD=1e9+7;
#define int long long
int n,m,f[o][2],g[o][2],s[o],ans;
signed main(){
	read(n);read(m);
	f[0][0]=g[0][0]=1;
	for(int i=1,a=1;i<=n;a=a*(++i)%MOD){for(int j=1;j<=n;++j) s[j]=((g[j][1]=(MOD*3ll-s[j-1]+(j>m?s[j-m-1]:0)-(j>m?2*f[j-m-1][0]:0))%MOD)+
	s[j-1])%MOD,f[j][1]=(g[j][1]+f[j-1][0])%MOD;for(int j=0;j<=n;++j) f[j][0]=f[j][1],g[j][0]=g[j][1];ans=(ans+a*f[n][0])%MOD;}write(ans);
	return 0;
}

上一题