题意
若一个1 ~ n的排列中存在一个区间使得这个区间内元素的最大值与最小值之差为,则称其为一个片段,显然所有长度为1的区间均为一个片段。现在给定n与一个素数m,求1 ~ n的全排列中所有片段数之和对m取模的结果。
思路
这题是个DP,乍一看没有什么想法简单暴力显然行不通,求出每个排列然后依次统计必然是TLE的。
所以我们换一个思路,求出每种长度的片段数,再计算一下对于每种长度的片段,它在所有 ~ 的排列中有多少种放法,把它们乘起来求和就搞定了。
具体来说,对于 ~ 的排列,长度为的片段,假设这个片段包含的元素为 ~ :
- 这个片段自身有种排列方式
- 剩下有个数,则这个片段可以放置在个不同的位置(在它前面分别有0,1,…,个数)
- 剩下的个数有种排列方式
- L的取值有 ~ 共种
所以对于长度为的片段,总共有种放置方式,枚举考虑的情况求和即可。
然后我因为忘记取模wa了3发
保险起见,最好在每次乘积之后都进行一次取模运算。
AC代码
#include<stdio.h>
long long m,n;
long long mu[250005];
long long ans;
int main()
{
scanf("%I64d%I64d",&n,&m);
mu[0]=1;
for(int i=1;i<=250000;i++)
{mu[i]=mu[i-1]*(long long)i;mu[i]%=m;};
for(int i=1;i<=n;i++)
{
ans+=((((mu[i]*mu[n-i]%m)*(n-((long long)i-1))%m)*(n-((long long)i-1)))%m);
ans%=m;
}
printf("%I64d",ans);
return 0;
}
来源:CSDN
作者:asdkjc
链接:https://blog.csdn.net/weixin_44582673/article/details/103933946