codeforces 1284C. New Year and Permutation(组合数学)
链接:https://codeforces.com/problemset/problem/1284/C
题意:定义一个framed segment,在区间[l,r]中,max值-min值 = r - l。求有1-n 组成的序列中,所有framed segment的个数%m
思路:组合数学推一个结论。例如假设1到n组成的序列中,求长度为k的framed segment,那么其一段序列的最大值 - 最小值 = k,例如n = 5,k = 3,这些framed segment 必定是 1 2 3 或者2 3 4 或者 3 4 5,可以观测到其长度为k的framed segment必定是连续的,可以把他们单独算一个整体,这样序列总体长度变为n - k + 1,内部长度为k,内部组合种类就是k!个,总体组合种类就是(n-k+1)!,长度为k的framed segment种类又是(123,234,345)n - k + 1种,所以长度为k的framed segment 最终答案就是(n-k+1)*(n-k+1)!*k!,预处理一下阶乘即可。
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 typedef long long ll; 9 const int maxn = 2e5+5e4+5; 10 ll fac[maxn]; 11 int main(){ 12 ll n,m; 13 cin>>n>>m; 14 fac[1] = 1; 15 for(int i = 2;i<=n;i++){ 16 fac[i] = (fac[i-1]*i)%m; 17 } 18 ll ans = 0; 19 for(int i = 1;i<=n;i++){ 20 ans +=((n+1-i)*(fac[i])%m)*(fac[n+1-i])%m; 21 ans = ans%m; 22 } 23 // 1 2 3 24 cout<<ans%m; 25 return 0; 26 }