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 }

猜你喜欢

转载自www.cnblogs.com/AaronChang/p/12185455.html